autumnnote 1.0.9 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -10
- package/dist/autumnnote.css +169 -0
- package/dist/autumnnote.es.js +806 -23
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +806 -23
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +24 -4
- package/src/js/Context.js +14 -2
- package/src/js/core/func.js +5 -5
- package/src/js/index.js +1 -1
- package/src/js/module/AutoSaveRestore.js +126 -0
- package/src/js/module/BubbleToolbar.js +243 -0
- package/src/js/module/ContextMenu.js +28 -26
- package/src/js/module/MarkdownShortcuts.js +253 -0
- package/src/js/module/Mention.js +337 -0
- package/src/js/settings.js +19 -0
- package/src/styles/autumnnote.scss +191 -0
- package/types/index.d.ts +56 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autumnnote.es.js","names":["Style.bold","Style.italic","Style.underline","Style.strikethrough","Style.superscript","Style.subscript","Style.justifyLeft","Style.justifyCenter","Style.justifyRight","Style.justifyFull","Style.insertUnorderedList","Style.insertOrderedList","Style.indent","Style.outdent","Style.execCommand","Style.fontSize","Style.fontName","Style.formatBlock","Style.lineHeight","Style.isInlineCode","Style.isInChecklist","Style.foreColor","Style.backColor","HANDLE_DEFS","ICONS","SHOW_DELAY","HIDE_DELAY","ICONS","SHOW_DELAY","HIDE_DELAY","ICONS","SHOW_DELAY","HIDE_DELAY","SHOW_DELAY","HIDE_DELAY","ICONS","ICONS","clamp"],"sources":["../src/js/core/func.js","../src/js/core/dom.js","../src/js/core/range.js","../src/js/editing/Style.js","../src/js/module/Buttons.js","../src/js/settings.js","../src/js/i18n/en.js","../src/js/i18n/vi.js","../src/js/i18n/ja.js","../src/js/i18n/zh.js","../src/js/i18n/fr.js","../src/js/i18n/de.js","../src/js/i18n/es.js","../src/js/i18n/ko.js","../src/js/i18n/index.js","../src/js/core/sanitise.js","../src/js/renderer.js","../src/js/editing/History.js","../src/js/editing/Table.js","../src/js/core/key.js","../src/js/editing/Typing.js","../src/js/core/markdown.js","../src/js/module/Editor.js","../src/js/module/Toolbar.js","../src/js/module/Statusbar.js","../src/js/module/Clipboard.js","../src/js/module/Placeholder.js","../src/js/module/Codeview.js","../src/js/module/Fullscreen.js","../src/js/module/LinkDialog.js","../src/js/module/ImageDialog.js","../src/js/module/VideoDialog.js","../src/js/module/ImageResizer.js","../src/js/module/VideoResizer.js","../src/js/module/LinkTooltip.js","../src/js/module/ImageTooltip.js","../src/js/module/VideoTooltip.js","../src/js/module/TableTooltip.js","../src/js/module/CodeTooltip.js","../src/js/module/EmojiDialog.js","../src/js/module/IconDialog.js","../src/js/module/ContextMenu.js","../src/js/module/ShortcutsDialog.js","../src/js/module/FindReplace.js","../src/js/module/ImageCropOverlay.js","../src/js/Context.js","../src/js/core/lists.js","../src/js/core/env.js","../src/js/index.js"],"sourcesContent":["/**\n * func.js - General utility / functional helpers\n * Inspired by Summernote's func.js\n */\n\n/**\n * Clamp a value between min and max.\n * @param {number} val\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\nexport function clamp(val, min, max) {\n return Math.min(Math.max(val, min), max);\n}\n\n/**\n * Debounce a function call.\n * @param {Function} fn\n * @param {number} delay - milliseconds\n * @returns {Function}\n */\nexport function debounce(fn, delay) {\n let timer;\n return function (...args) {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n\n/**\n * Throttle a function call.\n * @param {Function} fn\n * @param {number} limit - milliseconds\n * @returns {Function}\n */\nexport function throttle(fn, limit) {\n let lastCall = 0;\n return function (...args) {\n const now = Date.now();\n if (now - lastCall >= limit) {\n lastCall = now;\n return fn.apply(this, args);\n }\n };\n}\n\n/**\n * Compose multiple functions right-to-left.\n * @param {...Function} fns\n * @returns {Function}\n */\nexport function compose(...fns) {\n return (x) => fns.reduceRight((v, f) => f(v), x);\n}\n\n/**\n * Identity function.\n * @template T\n * @param {T} x\n * @returns {T}\n */\nexport function identity(x) {\n return x;\n}\n\n/**\n * Determines if a value is null or undefined.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isNil(val) {\n return val === null || val === undefined;\n}\n\n/**\n * Determines if a value is a string.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determines if a value is a function.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isFunction(val) {\n return typeof val === 'function';\n}\n\n/**\n * Deep-merge two plain objects. Returns a new object.\n * Arrays are cloned (shallow copy) rather than shared by reference so that\n * mutations to the merged result do not bleed back into the source object\n * (e.g. mutating `instance.options.fontFamilies` should not affect\n * `AutumnNote.defaults.fontFamilies`).\n * @param {object} target\n * @param {object} source\n * @returns {object}\n */\nexport function mergeDeep(target, source) {\n // Start with a shallow copy of target; clone any arrays to avoid shared refs\n const output = {};\n for (const key of Object.keys(target)) {\n output[key] = Array.isArray(target[key]) ? [...target[key]] : target[key];\n }\n if (isPlainObject(target) && isPlainObject(source)) {\n for (const key of Object.keys(source)) {\n if (isPlainObject(source[key])) {\n if (!(key in target)) {\n output[key] = mergeDeep({}, source[key]);\n } else {\n output[key] = mergeDeep(target[key], source[key]);\n }\n } else if (Array.isArray(source[key])) {\n output[key] = [...source[key]];\n } else {\n output[key] = source[key];\n }\n }\n }\n return output;\n}\n\n/**\n * Checks if value is a plain object.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isPlainObject(val) {\n return val !== null && typeof val === 'object' && !Array.isArray(val);\n}\n\n/**\n * Convert a DOMRect (or similar bounding object) to a plain object bounding box.\n * Guards against missing/null rect (e.g. in AirMode).\n * @param {DOMRect|null|undefined} rect\n * @returns {{ top: number, left: number, width: number, height: number, bottom: number, right: number }|null}\n */\nexport function rect2bnd(rect) {\n if (!rect) return null;\n return {\n top: Math.round(rect.top),\n left: Math.round(rect.left),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n bottom: Math.round(rect.bottom),\n right: Math.round(rect.right),\n };\n}\n","/**\n * dom.js - DOM manipulation utilities\n * Inspired by Summernote's dom.js — rewritten for vanilla JS without jQuery\n */\n\n// ---------------------------------------------------------------------------\n// Node type helpers\n// ---------------------------------------------------------------------------\n\nexport const ELEMENT_NODE = 1;\nexport const TEXT_NODE = 3;\n\n/** @param {Node} node */\nexport const isElement = (node) => node && node.nodeType === ELEMENT_NODE;\n/** @param {Node} node */\nexport const isText = (node) => node && node.nodeType === TEXT_NODE;\n/** @param {Node} node */\nexport const isVoid = (node) => isElement(node) && /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isPara = (node) => isElement(node) && /^(p|div|li|h[1-6]|blockquote|td|th|pre)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isLi = (node) => isElement(node) && /^(li)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isList = (node) => isElement(node) && /^(ul|ol)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isTable = (node) => isElement(node) && node.nodeName.toUpperCase() === 'TABLE';\n/** @param {Node} node */\nexport const isInline = (node) =>\n isElement(node) &&\n /^(a|abbr|acronym|b|bdo|big|br|button|cite|code|dfn|em|i|img|input|kbd|label|map|object|output|q|s|samp|select|small|span|strong|sub|sup|textarea|time|tt|u|var)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isEditable = (node) => isElement(node) && node.isContentEditable;\n/** @param {Node} node */\nexport const isAnchor = (node) => isElement(node) && node.nodeName.toUpperCase() === 'A';\n/** @param {Node} node */\nexport const isImage = (node) => isElement(node) && node.nodeName.toUpperCase() === 'IMG';\n\n// ---------------------------------------------------------------------------\n// Tree traversal\n// ---------------------------------------------------------------------------\n\n/**\n * Walk up the DOM tree from node, returning the first element matching predicate (inclusive).\n * @param {Node} node\n * @param {(node: Node) => boolean} predicate\n * @param {Node} [stopAt] - stop traversal at this ancestor (exclusive)\n * @returns {Node|null}\n */\nexport function closest(node, predicate, stopAt) {\n let cur = node;\n while (cur && cur !== stopAt) {\n if (predicate(cur)) return cur;\n cur = cur.parentNode;\n }\n return null;\n}\n\n/**\n * Returns the nearest ancestor that is a paragraph-like block.\n * @param {Node} node\n * @param {Node} [editable]\n * @returns {Node|null}\n */\nexport function closestPara(node, editable) {\n return closest(node, isPara, editable);\n}\n\n/**\n * Returns all ancestors of node up to (but not including) stopAt.\n * @param {Node} node\n * @param {Node} [stopAt]\n * @returns {Node[]}\n */\nexport function ancestors(node, stopAt) {\n const result = [];\n let cur = node.parentNode;\n while (cur && cur !== stopAt) {\n result.push(cur);\n cur = cur.parentNode;\n }\n return result;\n}\n\n/**\n * Returns all children of node as an Array.\n * @param {Node} node\n * @returns {Node[]}\n */\nexport function children(node) {\n return Array.from(node.childNodes);\n}\n\n/**\n * Returns the previous sibling element (skipping text/comment nodes).\n * @param {Node} node\n * @returns {Element|null}\n */\nexport function prevElement(node) {\n let sibling = node.previousSibling;\n while (sibling && !isElement(sibling)) {\n sibling = sibling.previousSibling;\n }\n return sibling;\n}\n\n/**\n * Returns the next sibling element.\n * @param {Node} node\n * @returns {Element|null}\n */\nexport function nextElement(node) {\n let sibling = node.nextSibling;\n while (sibling && !isElement(sibling)) {\n sibling = sibling.nextSibling;\n }\n return sibling;\n}\n\n// ---------------------------------------------------------------------------\n// DOM mutation helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an element with optional attributes and children.\n * @param {string} tag\n * @param {Record<string, string>} [attrs]\n * @param {(Node|string)[]} [childNodes]\n * @returns {HTMLElement}\n */\nexport function createElement(tag, attrs = {}, childNodes = []) {\n const el = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n el.setAttribute(k, v);\n }\n for (const child of childNodes) {\n if (typeof child === 'string') {\n el.appendChild(document.createTextNode(child));\n } else {\n el.appendChild(child);\n }\n }\n return el;\n}\n\n/**\n * Removes a node from its parent.\n * @param {Node} node\n */\nexport function remove(node) {\n if (node && node.parentNode) {\n node.parentNode.removeChild(node);\n }\n}\n\n/**\n * Unwraps a node — replaces the node with its children.\n * @param {Node} node\n */\nexport function unwrap(node) {\n const parent = node.parentNode;\n if (!parent) return;\n while (node.firstChild) {\n parent.insertBefore(node.firstChild, node);\n }\n parent.removeChild(node);\n}\n\n/**\n * Wraps a node with a wrapper element.\n * @param {Node} node\n * @param {HTMLElement} wrapper\n * @returns {HTMLElement} the wrapper\n */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Insert node after reference node.\n * @param {Node} newNode\n * @param {Node} refNode\n */\nexport function insertAfter(newNode, refNode) {\n if (refNode.nextSibling) {\n refNode.parentNode.insertBefore(newNode, refNode.nextSibling);\n } else {\n refNode.parentNode.appendChild(newNode);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Content helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the text content of a node (safe).\n * @param {Node} node\n * @returns {string}\n */\nexport function nodeValue(node) {\n return isText(node) ? node.nodeValue : node.textContent || '';\n}\n\n/**\n * Returns true if a node is empty (no visible content).\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isEmpty(node) {\n if (isText(node)) return !node.nodeValue;\n if (isVoid(node)) return false;\n return !node.textContent.trim() && !node.querySelector('img, video, hr, table');\n}\n\n/**\n * Returns the outerHTML of an element.\n * @param {Element} el\n * @returns {string}\n */\nexport function outerHtml(el) {\n return el.outerHTML;\n}\n\n// ---------------------------------------------------------------------------\n// Selection / editing helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Places the caret at the end of a contenteditable element.\n * @param {HTMLElement} el\n */\nexport function placeCaret(el) {\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n }\n}\n\n/**\n * Returns true if the node is inside a contenteditable root.\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isInsideEditable(node) {\n return !!closest(node, isEditable);\n}\n\n// ---------------------------------------------------------------------------\n// Event helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Adds an event listener and returns a disposer function.\n * @param {EventTarget} target\n * @param {string} type\n * @param {EventListener} handler\n * @param {AddEventListenerOptions} [options]\n * @returns {() => void} disposer\n */\nexport function on(target, type, handler, options) {\n target.addEventListener(type, handler, options);\n return () => target.removeEventListener(type, handler, options);\n}\n\n/**\n * Installs a keyboard focus trap inside a dialog container.\n * - Tab / Shift+Tab cycles focus within the container's focusable children.\n * - Escape calls `onEscape` and removes the trap listener.\n *\n * Returns a disposer function that removes the listener (call on dialog close).\n *\n * @param {HTMLElement} container - the dialog element to trap focus inside\n * @param {() => void} onEscape - called when Escape is pressed\n * @returns {() => void} disposer\n */\nexport function trapFocus(container, onEscape) {\n const FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n const getFocusable = () => Array.from(container.querySelectorAll(FOCUSABLE)).filter(\n (el) => !el.closest('[style*=\"display: none\"]') && !el.closest('[style*=\"display:none\"]'),\n );\n\n const handler = (e) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onEscape && onEscape();\n return;\n }\n if (e.key !== 'Tab') return;\n const els = getFocusable();\n if (!els.length) return;\n const first = els[0];\n const last = els[els.length - 1];\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n}\n","/**\n * range.js - Selection and Range utilities\n * Inspired by Summernote's range.js — rewritten as vanilla JS\n */\n\nimport { isElement, closest } from './dom.js';\n\n// ---------------------------------------------------------------------------\n// WrappedRange — a convenience wrapper over the native Range API\n// ---------------------------------------------------------------------------\n\nexport class WrappedRange {\n /**\n * @param {Node} sc - start container\n * @param {number} so - start offset\n * @param {Node} ec - end container\n * @param {number} eo - end offset\n */\n constructor(sc, so, ec, eo) {\n this.sc = sc;\n this.so = so;\n this.ec = ec;\n this.eo = eo;\n }\n\n /** @returns {boolean} */\n isCollapsed() {\n return this.sc === this.ec && this.so === this.eo;\n }\n\n /** @returns {Range} */\n toNativeRange() {\n const range = document.createRange();\n try {\n range.setStart(this.sc, this.so);\n range.setEnd(this.ec, this.eo);\n } catch (_e) {\n // Guard against detached nodes\n }\n return range;\n }\n\n /**\n * Select this wrapped range in the window.\n */\n select() {\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(this.toNativeRange());\n }\n\n /**\n * Returns the common ancestor element of this range.\n * @returns {Element|null}\n */\n commonAncestor() {\n const native = this.toNativeRange();\n const ancestor = native.commonAncestorContainer;\n return isElement(ancestor) ? ancestor : ancestor.parentElement;\n }\n\n /**\n * Returns the nearest paragraph/block ancestor within the editable area.\n * @param {HTMLElement} editable\n * @returns {Element|null}\n */\n blockNode(editable) {\n return closest(this.sc, (n) => isElement(n) && n !== editable, editable);\n }\n\n /**\n * Returns either the selected text string or empty string.\n * @returns {string}\n */\n toString() {\n return this.toNativeRange().toString();\n }\n\n /**\n * Returns the bounding DOMRect of the range (or null).\n * @returns {DOMRect|null}\n */\n getClientRects() {\n const rects = this.toNativeRange().getClientRects();\n return rects.length > 0 ? rects[rects.length - 1] : null;\n }\n\n /**\n * Inserts a node at the start of this range.\n * @param {Node} node\n */\n insertNode(node) {\n const native = this.toNativeRange();\n native.insertNode(node);\n }\n\n}\n\n// ---------------------------------------------------------------------------\n// Factory helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a WrappedRange from a native Range object.\n * @param {Range} range\n * @returns {WrappedRange}\n */\nexport function fromNativeRange(range) {\n return new WrappedRange(\n range.startContainer,\n range.startOffset,\n range.endContainer,\n range.endOffset,\n );\n}\n\n/**\n * Returns a WrappedRange for the current window selection,\n * optionally restricted to a given editable element.\n * @param {HTMLElement} [editable]\n * @returns {WrappedRange|null}\n */\nexport function currentRange(editable) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const native = sel.getRangeAt(0);\n // Optionally check that the selection is inside the editable element\n if (editable && !editable.contains(native.commonAncestorContainer)) {\n return null;\n }\n return fromNativeRange(native);\n}\n\n/**\n * Creates a WrappedRange that covers the entire content of an element.\n * @param {HTMLElement} el\n * @returns {WrappedRange}\n */\nexport function rangeFromElement(el) {\n return new WrappedRange(el, 0, el, el.childNodes.length);\n}\n\n/**\n * Creates a collapsed range (cursor) at the given node / offset.\n * @param {Node} node\n * @param {number} offset\n * @returns {WrappedRange}\n */\nexport function collapsedRange(node, offset = 0) {\n return new WrappedRange(node, offset, node, offset);\n}\n\n// ---------------------------------------------------------------------------\n// Utility helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns true if the current selection is inside the given element.\n * @param {HTMLElement} el\n * @returns {boolean}\n */\nexport function isSelectionInside(el) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return false;\n return el.contains(sel.getRangeAt(0).commonAncestorContainer);\n}\n\n/**\n * Saves the current selection, executes fn, then restores the selection.\n * @param {Function} fn\n */\nexport function withSavedRange(fn) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) {\n fn(null);\n return;\n }\n const saved = sel.getRangeAt(0).cloneRange();\n fn(fromNativeRange(saved));\n sel.removeAllRanges();\n sel.addRange(saved);\n}\n\n/**\n * Splits the text node at the given offset and returns the two halves.\n * @param {Text} textNode\n * @param {number} offset\n * @returns {[Text, Text]}\n */\nexport function splitText(textNode, offset) {\n const after = textNode.splitText(offset);\n return [textNode, after];\n}\n","/**\n * Style.js - Inline / block style detection and application utilities\n * Rewritten from Summernote's approach using vanilla JS + execCommand fallback\n */\n\nimport { closest, isElement, isPara } from '../core/dom.js';\nimport { currentRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// execCommand wrappers (still the most compatible way in contenteditable)\n// ---------------------------------------------------------------------------\n\n/**\n * Applies a document execCommand.\n * @param {string} cmd\n * @param {string} [value]\n * @returns {boolean}\n */\nexport function execCommand(cmd, value = null) {\n return document.execCommand(cmd, false, value);\n}\n\n// ---------------------------------------------------------------------------\n// Inline style helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Bolds / unbolds the selection.\n */\nexport const bold = () => execCommand('bold');\n\n/**\n * Italicises / un-italicises the selection.\n */\nexport const italic = () => execCommand('italic');\n\n/**\n * Underlines / un-underlines the selection.\n * Falls back to manual DOM manipulation when inside <code> where\n * execCommand's state detection is unreliable.\n */\nexport function underline() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n // Check if we're inside a <u> (DOM truth), to guard against unreliable queryCommandState\n const uEl = container && container.closest && container.closest('u');\n const nativeState = document.queryCommandState('underline');\n if (uEl && !nativeState) {\n // Browser doesn't recognise the underline state (e.g. inside <code>).\n // Manually unwrap the <u> element.\n const parent = uEl.parentNode;\n while (uEl.firstChild) parent.insertBefore(uEl.firstChild, uEl);\n parent.removeChild(uEl);\n return;\n }\n execCommand('underline');\n}\n\n/**\n * Strikethrough / removes strikethrough.\n * Falls back to manual DOM manipulation inside nested formats where\n * execCommand's state detection is unreliable (mirrors underline() logic).\n */\nexport function strikethrough() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n // Use startContainer for consistent detection across collapsed and range\n // selections — commonAncestorContainer can miss ancestor <s>/<strike> tags\n // when the selection spans across nested inline elements.\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n const sEl = sc && sc.closest && (sc.closest('s') || sc.closest('strike'));\n const nativeState = document.queryCommandState('strikeThrough');\n if (sEl && !nativeState) {\n // Browser doesn’t recognise the strikethrough state (e.g. inside <code>\n // or deeply nested inline formats). Manually unwrap the <s>/<strike>.\n const parent = sEl.parentNode;\n while (sEl.firstChild) parent.insertBefore(sEl.firstChild, sEl);\n parent.removeChild(sEl);\n return;\n }\n execCommand('strikeThrough');\n}\n\n/**\n * Superscript toggle.\n */\nexport const superscript = () => execCommand('superscript');\n\n/**\n * Subscript toggle.\n */\nexport const subscript = () => execCommand('subscript');\n\n/**\n * Sets the foreground colour of the selected text.\n * @param {string} color - CSS colour string\n */\nexport const foreColor = (color) => execCommand('foreColor', color);\n\n/**\n * Sets the background (highlight) colour of the selected text.\n * @param {string} color - CSS colour string\n */\nexport const backColor = (color) => execCommand('hiliteColor', color);\n\n/**\n * Sets the font name for the selection.\n * @param {string} name\n */\nexport const fontName = (name) => execCommand('fontName', name);\n\n/**\n * Sets the font size (in pt or with unit) for the selection.\n * Uses a span-based approach to set px sizes precisely.\n * @param {string} size - e.g. '14px'\n * @param {HTMLElement} [editable] - scoping element to avoid touching nodes outside this editor\n */\nexport function fontSize(size, editable = document) {\n const sel = window.getSelection();\n const wasCollapsed = !sel || !sel.rangeCount || sel.getRangeAt(0).collapsed;\n\n // B-I-3/4: For a collapsed (caret) selection the browser's execCommand\n // 'fontSize' leaves an internal \"pending\" state of size-7 (=48px) instead of\n // creating a <font> element, so the very next typed character comes out at\n // 48px. Fix: bypass execCommand entirely for collapsed selections and directly\n // insert a span with the requested size, placing the cursor inside it.\n // Only applies when there IS an active selection (sel.rangeCount > 0); when\n // there is no selection at all (e.g. jsdom unit tests) fall through to the\n // execCommand path so the font-replacement logic still runs.\n if (wasCollapsed && sel && sel.rangeCount > 0) {\n try {\n const range = sel.getRangeAt(0);\n const span = document.createElement('span');\n span.style.fontSize = size;\n const zwsNode = document.createTextNode('\\u200B');\n span.appendChild(zwsNode);\n range.insertNode(span);\n const nr = document.createRange();\n nr.setStart(zwsNode, zwsNode.textContent.length);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n } catch (_) { /* ignore range errors on unusual DOM structures */ }\n return;\n }\n\n // Non-collapsed selection (or no selection — handles jsdom test setup where\n // <font size=\"7\"> elements are injected directly without a live selection):\n // use execCommand placeholder approach then replace <font> with <span>.\n execCommand('fontSize', '7');\n const scope = editable instanceof HTMLElement ? editable : document;\n const newSpans = [];\n scope.querySelectorAll('font[size=\"7\"]').forEach((el) => {\n const span = document.createElement('span');\n span.style.fontSize = size;\n el.parentNode.insertBefore(span, el);\n while (el.firstChild) span.appendChild(el.firstChild);\n el.parentNode.removeChild(el);\n newSpans.push(span);\n });\n\n // Re-select all replaced content so toolbar getValue() reads the new size\n // (B-I-1/2: without this re-selection the toolbar dropdown stays on the old\n // value until the next selectionchange event).\n if (!wasCollapsed && sel && newSpans.length > 0) {\n const first = newSpans[0];\n const last = newSpans[newSpans.length - 1];\n try {\n const nr = document.createRange();\n const startNode = first.firstChild || first;\n const endNode = last.lastChild || last;\n nr.setStart(startNode, 0);\n nr.setEnd(endNode, endNode.nodeType === Node.TEXT_NODE ? endNode.textContent.length : endNode.childNodes.length);\n sel.removeAllRanges();\n sel.addRange(nr);\n } catch (_) { /* ignore range errors on unusual DOM structures */ }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Block style helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps the selection in the given block tag (p, h1-h6, blockquote, pre).\n * @param {string} tagName\n */\nexport const formatBlock = (tagName) => execCommand('formatBlock', `<${tagName}>`);\n\n/**\n * Left-aligns the current block.\n */\nexport const justifyLeft = () => execCommand('justifyLeft');\n\n/**\n * Center-aligns the current block.\n */\nexport const justifyCenter = () => execCommand('justifyCenter');\n\n/**\n * Right-aligns the current block.\n */\nexport const justifyRight = () => execCommand('justifyRight');\n\n/**\n * Fully justifies the current block.\n */\nexport const justifyFull = () => execCommand('justifyFull');\n\n/**\n * Indents the list or block.\n */\nexport const indent = () => execCommand('indent');\n\n/**\n * Outdents the list or block.\n * G.5: When cursor is inside a checklist item, \"outdent\" means converting\n * that item back to a regular <p> element rather than calling execCommand\n * (which would destroy the ul > li checklist structure).\n */\nexport function outdent() {\n const sel = window.getSelection();\n if (sel && sel.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const checkLi = container && container.closest && container.closest('.an-checklist li');\n if (checkLi) {\n _checklistItemToP(checkLi);\n return;\n }\n }\n execCommand('outdent');\n}\n\n/**\n * G.5 helper: splits a checklist at checkLi, converts it to a <p>,\n * and keeps items before/after as separate checklists.\n * @param {HTMLElement} checkLi\n */\nfunction _checklistItemToP(checkLi) {\n const checkUl = checkLi.closest('.an-checklist');\n if (!checkUl) return;\n\n const allLis = Array.from(checkUl.children);\n const liIndex = allLis.indexOf(checkLi);\n const afterLis = allLis.slice(liIndex + 1);\n\n // Build <p> from the item's text (skip the checkbox INPUT)\n const p = document.createElement('p');\n const text = Array.from(checkLi.childNodes)\n .filter(n => !(n.nodeType === 1 && n.tagName === 'INPUT'))\n .map(n => n.textContent).join('').replace(/\\u200B/g, '').trim();\n p.textContent = text || '\\u00a0';\n\n // Move items after the current li into a new checklist\n if (afterLis.length > 0) {\n const newUl = document.createElement('ul');\n newUl.className = 'an-checklist';\n afterLis.forEach(li => newUl.appendChild(li));\n checkUl.parentNode.insertBefore(newUl, checkUl.nextSibling);\n }\n\n // Insert <p> after checkUl (before any newUl)\n checkUl.parentNode.insertBefore(p, checkUl.nextSibling);\n\n // Remove current li from checkUl; delete checkUl if now empty\n checkUl.removeChild(checkLi);\n if (checkUl.children.length === 0) checkUl.parentNode.removeChild(checkUl);\n\n // Place caret at start of the new <p>\n try {\n const nr = document.createRange();\n const firstChild = p.firstChild;\n nr.setStart(firstChild && firstChild.nodeType === 3 ? firstChild : p, 0);\n nr.collapse(true);\n const s = window.getSelection();\n if (s) { s.removeAllRanges(); s.addRange(nr); }\n } catch {}\n}\n\n/**\n * Inserts an unordered list or converts selection.\n */\nexport const insertUnorderedList = () => execCommand('insertUnorderedList');\n\n/**\n * Inserts an ordered list or converts selection.\n */\nexport const insertOrderedList = () => execCommand('insertOrderedList');\n\n// ---------------------------------------------------------------------------\n// Line-height helper\n// ---------------------------------------------------------------------------\n\n/**\n * Applies a line-height value to every block-level element that intersects\n * the current selection.\n * @param {string} value - unitless multiplier, e.g. '1.5'\n */\nexport function lineHeight(value) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n\n const range = sel.getRangeAt(0);\n const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE', 'PRE', 'TD', 'TH']);\n\n const nearestBlock = (node) => {\n let el = node instanceof Element ? node : node.parentElement;\n while (el) {\n if (BLOCK_TAGS.has(el.tagName)) return el;\n el = el.parentElement;\n }\n return null;\n };\n\n if (range.collapsed) {\n const block = nearestBlock(range.startContainer);\n if (block) block.style.lineHeight = value;\n return;\n }\n\n // For a range selection, collect all unique block ancestors of text nodes\n const blocks = new Set();\n const iter = document.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_TEXT, null);\n let textNode;\n while ((textNode = iter.nextNode())) {\n if (range.intersectsNode(textNode)) {\n const block = nearestBlock(textNode);\n if (block) blocks.add(block);\n }\n }\n if (blocks.size === 0) {\n const block = nearestBlock(range.commonAncestorContainer);\n if (block) blocks.add(block);\n }\n blocks.forEach((block) => { block.style.lineHeight = value; });\n}\n\n// ---------------------------------------------------------------------------\n// Style query helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the computed styles relevant to the current cursor position.\n * @param {HTMLElement} editable\n * @returns {object} styleMap\n */\nexport function currentStyle(editable) {\n const range = currentRange(editable);\n if (!range) return {};\n\n const container = range.isCollapsed()\n ? range.sc\n : range.commonAncestor();\n\n const el = isElement(container) ? container : container.parentElement;\n if (!el) return {};\n\n const computed = window.getComputedStyle(el);\n\n return {\n bold: document.queryCommandState('bold'),\n italic: document.queryCommandState('italic'),\n underline: document.queryCommandState('underline'),\n strikethrough: document.queryCommandState('strikeThrough'),\n superscript: document.queryCommandState('superscript'),\n subscript: document.queryCommandState('subscript'),\n fontSize: computed.fontSize,\n fontFamily: computed.fontFamily,\n color: computed.color,\n backgroundColor: computed.backgroundColor,\n textAlign: computed.textAlign,\n lineHeight: computed.lineHeight,\n formatBlock: (closest(el, isPara, editable) || { nodeName: 'p' }).nodeName.toLowerCase(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Inline code toggle\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps the selection in an inline <code> element, or unwraps it if the\n * cursor is already inside a <code> that is not inside a <pre>.\n * @param {HTMLElement} [editable]\n */\nexport function toggleInlineCode(editable) {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n let container = range.commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const codeEl = container && container.closest ? container.closest('code') : null;\n if (codeEl && !codeEl.closest('pre')) {\n // Unwrap — save range endpoints relative to surrounding text so we can\n // restore the selection after normalize() merges adjacent text nodes.\n const parent = codeEl.parentNode;\n // Note the sibling before the code element so we can re-anchor later.\n const prevSibling = codeEl.previousSibling;\n const movedChildren = Array.from(codeEl.childNodes);\n while (codeEl.firstChild) parent.insertBefore(codeEl.firstChild, codeEl);\n parent.removeChild(codeEl);\n // Normalize only the immediate parent to merge adjacent text nodes without\n // invalidating distant selection anchors (full editable.normalize() can\n // cause selection offsets to shift, making subsequent format toggles miss).\n if (parent && parent.normalize) parent.normalize();\n // Restore selection to the text that was inside the unwrapped <code>.\n if (movedChildren.length > 0) {\n try {\n // After normalize, find the merged text node that contains the content.\n const firstMoved = movedChildren[0];\n const lastMoved = movedChildren[movedChildren.length - 1];\n const nr = document.createRange();\n // Use the (possibly merged) live node if still in the DOM.\n const anchorNode = (firstMoved.parentNode === parent) ? firstMoved : (prevSibling ? prevSibling.nextSibling : parent.firstChild);\n if (anchorNode) {\n nr.setStart(anchorNode, 0);\n const endAnchor = (lastMoved.parentNode === parent) ? lastMoved : anchorNode;\n nr.setEnd(endAnchor, endAnchor.nodeType === Node.TEXT_NODE ? endAnchor.textContent.length : endAnchor.childNodes.length);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n } catch (_) { /* ignore */ }\n }\n } else {\n if (range.collapsed) return;\n try {\n const code = document.createElement('code');\n range.surroundContents(code);\n // Re-select wrapped content so subsequent format toggles work\n const newRange = document.createRange();\n newRange.selectNodeContents(code);\n sel.removeAllRanges();\n sel.addRange(newRange);\n } catch {\n // surroundContents fails across element boundaries — extract and rewrap\n const frag = range.extractContents();\n const code = document.createElement('code');\n code.appendChild(frag);\n range.insertNode(code);\n // Re-select wrapped content\n const newRange = document.createRange();\n newRange.selectNodeContents(code);\n sel.removeAllRanges();\n sel.addRange(newRange);\n }\n }\n}\n\n/**\n * Returns true when the cursor / selection is inside an inline <code>\n * (not nested in a <pre>).\n * Uses startContainer for reliable cross-browser detection regardless of\n * whether the selection is collapsed or a range (commonAncestorContainer\n * can behave inconsistently for range selections on some browsers).\n * @returns {boolean}\n */\nexport function isInlineCode() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n const code = sc && sc.closest ? sc.closest('code') : null;\n return !!(code && !code.closest('pre'));\n}\n\n// ---------------------------------------------------------------------------\n// Checklist (task list)\n// ---------------------------------------------------------------------------\n\n/**\n * Toggles a task-list at the cursor.\n * If inside a checklist <li>, converts it (and any other selected items) back to <p> elements.\n * Otherwise inserts a new <ul class=\"an-checklist\"> with one item per selected line.\n */\nexport function toggleChecklist() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n let container = range.commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n\n const ul = container.closest && container.closest('.an-checklist');\n if (ul) {\n // If selection covers multiple <li>, convert them all\n const selectedLis = Array.from(ul.querySelectorAll('li')).filter((li) =>\n sel.containsNode(li, true),\n );\n if (selectedLis.length > 0) {\n let firstP = null;\n selectedLis.forEach((li) => {\n const text = Array.from(li.childNodes)\n .filter((n) => !(n.nodeType === 1 && n.tagName === 'INPUT'))\n .map((n) => n.textContent)\n .join('')\n .replace(/\\u00a0/g, ' ')\n .trim();\n const p = document.createElement('p');\n p.textContent = text || '\\u00a0';\n ul.parentNode.insertBefore(p, ul);\n if (!firstP) firstP = p;\n ul.removeChild(li);\n });\n if (ul.children.length === 0) ul.remove();\n // Move caret to first converted paragraph\n if (firstP) {\n const nr = document.createRange();\n nr.setStart(firstP.firstChild || firstP, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n return;\n }\n }\n\n // Otherwise: insert new checklist from selected text (or current block when collapsed).\n const isCollapsed = range.collapsed;\n if (isCollapsed) {\n // Find the nearest block-level ancestor (p, div, li, h1-h6, blockquote, etc.)\n // and convert it into a single checklist item.\n const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI']);\n let block = container;\n while (block && block.parentNode && !BLOCK_TAGS.has(block.tagName)) {\n block = block.parentNode;\n }\n // Fallback: if no block element found (e.g. cursor directly in editable root), use the\n // insertion approach with a zero-width-space item so the cursor ends up inside.\n const itemText = (block && BLOCK_TAGS.has(block.tagName))\n ? Array.from(block.childNodes)\n .map((n) => n.textContent)\n .join('')\n .replace(/\\u00a0/g, ' ')\n : '';\n\n const ul = document.createElement('ul');\n ul.className = 'an-checklist';\n const li = document.createElement('li');\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.contentEditable = 'false';\n li.appendChild(checkbox);\n li.appendChild(document.createTextNode(itemText || '\\u200B'));\n ul.appendChild(li);\n\n if (block && BLOCK_TAGS.has(block.tagName)) {\n block.parentNode.replaceChild(ul, block);\n } else {\n document.execCommand('insertHTML', false, ul.outerHTML);\n return;\n }\n\n // Move caret to the text node inside the new <li>\n const textNode = li.lastChild;\n const nr = document.createRange();\n const offset = textNode.nodeType === Node.TEXT_NODE ? textNode.textContent.length : 0;\n nr.setStart(textNode, offset);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return;\n }\n\n // G-4: Non-collapsed, non-checklist selection — convert each intersected\n // block element into a checklist item using direct DOM manipulation.\n // execCommand('insertHTML') is avoided here because in modern browsers it\n // deletes the selection but may silently fail to insert when the selection\n // spans multiple block elements, causing text to disappear.\n\n // Guard: if the raw selection is entirely whitespace, do nothing (mirrors\n // the old line-filter behaviour that prevented empty checklist creation).\n const rawSelText = sel.toString().replace(/[\\u00a0\\u200B]/g, ' ').trim();\n if (!rawSelText) return;\n\n const BLOCK_TAGS_MULTI = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'PRE', 'LI']);\n\n // Collect block-level ancestors of every node in the selection, in order.\n const blocks = [];\n const seenBlocks = new Set();\n const commonAncestor = range.commonAncestorContainer;\n const iter = document.createNodeIterator(\n commonAncestor.nodeType === Node.TEXT_NODE ? commonAncestor.parentNode : commonAncestor,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,\n null,\n );\n let node;\n while ((node = iter.nextNode())) {\n if (!range.intersectsNode(node)) continue;\n let block = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;\n while (block && !BLOCK_TAGS_MULTI.has(block.tagName)) {\n block = block.parentElement;\n }\n if (block && !seenBlocks.has(block)) {\n seenBlocks.add(block);\n blocks.push(block);\n }\n }\n\n if (blocks.length === 0) return;\n\n // Build checklist and replace collected blocks.\n const newUl = document.createElement('ul');\n newUl.className = 'an-checklist';\n let lastTextNode = null;\n blocks.forEach((block) => {\n const li = document.createElement('li');\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.setAttribute('contenteditable', 'false');\n li.appendChild(cb);\n // Preserve plain text content; ZWS/NBSP are stripped for display.\n const blockText = Array.from(block.childNodes)\n .map((n) => n.textContent)\n .join('')\n .replace(/[\\u00a0\\u200B]/g, ' ')\n .trim();\n const tn = document.createTextNode(blockText || '\\u200B');\n li.appendChild(tn);\n newUl.appendChild(li);\n lastTextNode = tn;\n });\n\n // Insert the new list before the first block, then remove all source blocks.\n const firstBlock = blocks[0];\n firstBlock.parentNode.insertBefore(newUl, firstBlock);\n blocks.forEach((block) => block.parentNode && block.parentNode.removeChild(block));\n\n // Move caret to end of the last checklist item.\n if (lastTextNode) {\n const nr = document.createRange();\n nr.setStart(lastTextNode, lastTextNode.textContent.length);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n}\n\n/**\n * Returns true when the cursor is inside a checklist item.\n * @returns {boolean}\n */\nexport function isInChecklist() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n return !!(container && container.closest && container.closest('.an-checklist li'));\n}\n","/**\n * Buttons.js - Toolbar button definitions and factories\n * All buttons are plain objects describing their appearance and action.\n * They are rendered by the Toolbar module.\n */\n\nimport * as Style from '../editing/Style.js';\n\n// ---------------------------------------------------------------------------\n// Dropdown definition helper\n// ---------------------------------------------------------------------------\n\n/**\n * @typedef {object} DropdownDef\n * @property {string} name - unique identifier\n * @property {'select'} type - discriminator for Toolbar renderer\n * @property {string} tooltip\n * @property {string[]} [items] - overridden at render time from options\n * @property {Function} action - called with (context, value)\n * @property {Function} [getValue] - called with (context) to get current value\n */\n\n// ---------------------------------------------------------------------------\n// Button factory helpers\n// ---------------------------------------------------------------------------\n\n/**\n * @typedef {object} ButtonDef\n * @property {string} name - unique identifier\n * @property {string} icon - SVG or HTML icon markup / text\n * @property {string} tooltip - tooltip string\n * @property {Function} action - called with (context) when clicked\n * @property {Function} [isActive] - called with (context) to determine active state\n * @property {Function} [isDisabled] - called with (context) to determine disabled state\n * @property {string} [className] - extra CSS class(es)\n */\n\n/**\n * Creates a simple button definition.\n * @param {string} name\n * @param {string} icon\n * @param {string} tooltip\n * @param {Function} action\n * @param {Function} [isActive]\n * @param {Function} [isDisabled]\n * @returns {ButtonDef}\n */\nfunction btn(name, icon, tooltip, action, isActive, isDisabled) {\n // `icon` is an identifier (e.g. 'bold', 'italic'). Rendering to\n // visual markup (FontAwesome or fallback) is done in Toolbar._createButton\n return { name, icon, tooltip, action, isActive, isDisabled };\n}\n\n// ---------------------------------------------------------------------------\n// Style buttons\n// ---------------------------------------------------------------------------\n\nexport const boldBtn = btn('bold', 'bold', 'Bold (Ctrl+B)', () => Style.bold(), () => document.queryCommandState('bold'));\nexport const italicBtn = btn('italic', 'italic', 'Italic (Ctrl+I)', () => Style.italic(), () => document.queryCommandState('italic'));\nexport const underlineBtn = btn('underline', 'underline', 'Underline (Ctrl+U)', () => Style.underline(), () => {\n // queryCommandState('underline') is unreliable inside <code> elements;\n // also check for a <u> ancestor in the DOM using startContainer for\n // consistent behaviour across both collapsed and range selections.\n if (document.queryCommandState('underline')) return true;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n return !!(sc && sc.closest && sc.closest('u'));\n});\nexport const strikeBtn = btn('strikethrough', 'strikethrough', 'Strikethrough', () => Style.strikethrough(), () => document.queryCommandState('strikeThrough'));\nexport const superscriptBtn = btn('superscript', 'superscript', 'Superscript', () => Style.superscript(), () => document.queryCommandState('superscript'));\nexport const subscriptBtn = btn('subscript', 'subscript', 'Subscript', () => Style.subscript(), () => document.queryCommandState('subscript'));\n\n// ---------------------------------------------------------------------------\n// Alignment buttons\n// ---------------------------------------------------------------------------\n\nexport const alignLeftBtn = btn('alignLeft', 'align-left', 'Align Left', () => Style.justifyLeft());\nexport const alignCenterBtn = btn('alignCenter', 'align-center', 'Align Center', () => Style.justifyCenter());\nexport const alignRightBtn = btn('alignRight', 'align-right', 'Align Right', () => Style.justifyRight());\nexport const alignJustifyBtn = btn('alignJustify', 'align-justify', 'Justify', () => Style.justifyFull());\n\n// ---------------------------------------------------------------------------\n// List buttons\n// ---------------------------------------------------------------------------\n\nexport const ulBtn = btn('ul', 'list-ul', 'Unordered List', () => Style.insertUnorderedList());\nexport const olBtn = btn('ol', 'list-ol', 'Ordered List', () => Style.insertOrderedList());\n\n// ---------------------------------------------------------------------------\n// Indent buttons\n// ---------------------------------------------------------------------------\n\nexport const indentBtn = btn('indent', 'indent', 'Indent', () => Style.indent());\nexport const outdentBtn = btn('outdent', 'outdent', 'Outdent', () => Style.outdent());\n\n// ---------------------------------------------------------------------------\n// Undo / redo buttons\n// ---------------------------------------------------------------------------\n\nexport const undoBtn = btn('undo', 'undo', 'Undo (Ctrl+Z)', (_ctx) => _ctx.invoke('editor.undo'), undefined, (ctx) => !ctx.invoke('editor.canUndo'));\nexport const redoBtn = btn('redo', 'redo', 'Redo (Ctrl+Y)', (_ctx) => _ctx.invoke('editor.redo'), undefined, (ctx) => !ctx.invoke('editor.canRedo'));\n\n// ---------------------------------------------------------------------------\n// Insert media — HR, Link, Image\n// ---------------------------------------------------------------------------\n\nexport const hrBtn = btn('hr', 'minus', 'Horizontal Rule', () => Style.execCommand('insertHorizontalRule'));\nexport const linkBtn = btn('link', 'link', 'Insert Link', (ctx) => ctx.invoke('linkDialog.show'));\nexport const imageBtn = btn('image', 'image', 'Insert Image', (ctx) => ctx.invoke('imageDialog.show'));\nexport const videoBtn = btn('video', 'video', 'Insert Video', (ctx) => ctx.invoke('videoDialog.show'));\nexport const emojiBtn = btn('emoji', 'emoji', 'Insert Emoji', (ctx) => ctx.invoke('emojiDialog.show'));\nexport const iconBtn = btn('icon', 'icon', 'Insert FA Icon', (ctx) => ctx.invoke('iconDialog.show'));\n\n/** @type {ButtonDef & { type: 'grid' }} */\nexport const tableBtn = {\n name: 'table',\n type: 'grid',\n icon: 'table',\n tooltip: 'Insert Table',\n action: (ctx, rows, cols) => {\n ctx.invoke('editor.insertTable', cols, rows);\n ctx.invoke('editor.afterCommand');\n },\n};\n\n// ---------------------------------------------------------------------------\n// Font size dropdown\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const fontSizeBtn = {\n name: 'fontSize',\n type: 'select',\n tooltip: 'Font Size',\n placeholder: 'Size',\n selectClass: 'an-select-narrow',\n items: ['8px', '10px', '11px', '12px', '13px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px', '72px'],\n action: (ctx, value) => Style.fontSize(value, ctx.layoutInfo.editable),\n getValue: (ctx) => {\n try {\n const sel = window.getSelection();\n if (sel && sel.rangeCount) {\n let el = sel.getRangeAt(0).startContainer;\n if (el.nodeType === 3) el = el.parentElement;\n while (el && el.nodeType === 1 && !el.style.fontSize) el = el.parentElement;\n const size = (el && el.style && el.style.fontSize) ? el.style.fontSize : '';\n if (size) return size;\n }\n // Fallback: read the base font size from the editable element itself\n const editable = ctx && ctx.layoutInfo && ctx.layoutInfo.editable;\n if (editable) return editable.style.fontSize || '';\n return '';\n } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Remove format button\n// ---------------------------------------------------------------------------\n\nexport const removeFormatBtn = btn('removeFormat', 'remove-format', 'Remove Format', () => Style.execCommand('removeFormat'));\n\n// ---------------------------------------------------------------------------\n// Direction (LTR / RTL) toggle button\n// ---------------------------------------------------------------------------\n\nexport const directionBtn = btn(\n 'direction',\n 'direction',\n 'Toggle Text Direction (LTR / RTL)',\n (ctx) => {\n const editable = ctx.layoutInfo.editable;\n const current = editable.getAttribute('dir') || 'ltr';\n const next = current === 'ltr' ? 'rtl' : 'ltr';\n editable.setAttribute('dir', next);\n editable.style.textAlign = next === 'rtl' ? 'right' : 'left';\n ctx.invoke('editor.afterCommand');\n },\n);\n\n// ---------------------------------------------------------------------------\n// Font family dropdown\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const fontFamilyBtn = {\n name: 'fontFamily',\n type: 'select',\n tooltip: 'Font Family',\n action: (ctx, value) => Style.fontName(value),\n getValue: () => {\n try { return document.queryCommandValue('fontName') || ''; } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Paragraph style dropdown (Normal / H1-H6 / Quote / Code)\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const paragraphStyleBtn = {\n name: 'paragraphStyle',\n type: 'select',\n tooltip: 'Paragraph Style',\n placeholder: 'Style',\n selectClass: 'an-select-style',\n items: [\n { value: 'p', label: 'Normal' },\n { value: 'h1', label: 'H1' },\n { value: 'h2', label: 'H2' },\n { value: 'h3', label: 'H3' },\n { value: 'h4', label: 'H4' },\n { value: 'h5', label: 'H5' },\n { value: 'h6', label: 'H6' },\n { value: 'blockquote', label: 'Quote' },\n { value: 'pre', label: 'Code' },\n ],\n action: (_ctx, value) => Style.formatBlock(value),\n getValue: () => {\n try {\n const raw = document.queryCommandValue('formatBlock').toLowerCase().replace(/[<>]/g, '');\n return raw === 'div' ? 'p' : (raw || 'p');\n } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Line-height dropdown\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const lineHeightBtn = {\n name: 'lineHeight',\n type: 'select',\n tooltip: 'Line Height',\n placeholder: '\\u2195 Line',\n selectClass: 'an-select-narrow',\n items: ['1.0', '1.15', '1.5', '1.75', '2.0', '2.5', '3.0'],\n action: (_ctx, value) => Style.lineHeight(value),\n getValue: () => {\n try {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return '';\n const BLOCKS = new Set(['P','DIV','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE','PRE','TD','TH']);\n let el = sel.getRangeAt(0).startContainer;\n if (el.nodeType === 3) el = el.parentElement;\n while (el && !BLOCKS.has(el.tagName)) el = el.parentElement;\n if (!el) return '';\n return el.style.lineHeight || getComputedStyle(el).lineHeight || '';\n } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Code view / fullscreen\n// ---------------------------------------------------------------------------\n\nexport const codeviewBtn = btn('codeview', 'code', 'HTML Code View', (ctx) => ctx.invoke('codeview.toggle'), (ctx) => ctx.invoke('codeview.isActive'));\nexport const fullscreenBtn = btn('fullscreen', 'expand', 'Fullscreen', (ctx) => ctx.invoke('fullscreen.toggle'), (ctx) => ctx.invoke('fullscreen.isActive'));\nexport const shortcutsBtn = btn('shortcuts', 'keyboard', 'Keyboard Shortcuts (Ctrl+Shift+/)', (ctx) => ctx.invoke('shortcutsDialog.show'));\nexport const findBtn = btn('find', 'search', 'Find (Ctrl+F)', (ctx) => ctx.invoke('findReplace.show', 'find'));\nexport const findReplaceBtn = btn('findReplace', 'find-replace', 'Find & Replace (Ctrl+H)', (ctx) => ctx.invoke('findReplace.show', 'replace'));\nexport const inlineCodeBtn = btn('inlineCode', 'inline-code', 'Inline Code (Ctrl+`)', (ctx) => ctx.invoke('editor.inlineCode'), () => Style.isInlineCode());\nexport const checklistBtn = btn('checklist', 'checklist', 'Checklist', (ctx) => ctx.invoke('editor.toggleChecklist'), () => Style.isInChecklist());\nexport const printBtn = btn('print', 'print', 'Print', (ctx) => ctx.invoke('editor.print'));\n\n// ---------------------------------------------------------------------------\n// Text / background colour pickers\n// ---------------------------------------------------------------------------\n\n/** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */\nexport const foreColorBtn = {\n name: 'foreColor',\n type: 'colorpicker',\n icon: 'foreColor',\n tooltip: 'Text Color',\n defaultColor: '#e11d48',\n action: (ctx, color) => Style.foreColor(color),\n};\n\n/** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */\nexport const backColorBtn = {\n name: 'backColor',\n type: 'colorpicker',\n icon: 'backColor',\n tooltip: 'Highlight Color',\n defaultColor: '#fbbf24',\n action: (ctx, color) => Style.backColor(color),\n};\n\n// ---------------------------------------------------------------------------\n// Default toolbar layout\n// ---------------------------------------------------------------------------\n\n/**\n * The default toolbar button groups.\n * Each sub-array is a button group (separated by a divider).\n */\nexport const defaultToolbar = [\n [paragraphStyleBtn, fontFamilyBtn, fontSizeBtn, lineHeightBtn],\n [undoBtn, redoBtn],\n [boldBtn, italicBtn, underlineBtn, strikeBtn, inlineCodeBtn],\n [superscriptBtn, subscriptBtn],\n [foreColorBtn, backColorBtn],\n [alignLeftBtn, alignCenterBtn, alignRightBtn, alignJustifyBtn],\n [ulBtn, olBtn, checklistBtn, indentBtn, outdentBtn],\n [hrBtn, linkBtn, imageBtn, videoBtn, tableBtn, emojiBtn, iconBtn],\n [removeFormatBtn, codeviewBtn, fullscreenBtn, findBtn, printBtn, shortcutsBtn],\n];\n","/**\n * settings.js - Default editor options\n * Inspired by Summernote's settings.js\n */\n\nimport { defaultToolbar } from './module/Buttons.js';\n\n/**\n * @typedef {object} AsnOptions\n * @property {string} [placeholder] - Placeholder text when editor is empty\n * @property {number} [height] - Editor height in px (min)\n * @property {number} [minHeight] - Minimum height in px\n * @property {number} [maxHeight] - Maximum height in px (0 = unlimited)\n * @property {boolean} [focus] - Auto-focus on init\n * @property {boolean} [resizable] - Show resize handle\n * @property {Array} [toolbar] - Toolbar button group config\n * @property {boolean} [pasteAsPlainText] - Force plain-text paste\n * @property {boolean} [pasteCleanHTML] - Sanitise HTML on paste\n * @property {boolean} [pasteStripAttributes] - Strip class/style/data-* from pasted HTML (default: false)\n * @property {boolean} [allowImageUpload] - Allow file upload in image dialog\n * @property {number} [maxImageSize] - Max upload size in MB\n * @property {number} [tabSize] - Spaces per tab in non-list context\n * @property {Function} [onChange] - Callback on content change\n * @property {Function} [onFocus] - Callback on focus\n * @property {Function} [onBlur] - Callback on blur\n * @property {Function} [onImageUpload] - Custom upload handler: (files) => void\n * @property {boolean} [stickyToolbar] - Stick the toolbar to the viewport top when scrolling\n * @property {number} [stickyToolbarOffset] - Top offset in px for sticky toolbar (e.g. fixed nav height)\n * @property {string} [theme] - 'light' (default) | 'dark'\n * @property {boolean} [codeHighlight] - Auto-load Prism.js for syntax highlighting of code blocks\n * @property {string} [codeHighlightCDN] - CDN base URL for Prism assets (defaults to cdnjs)\n * @property {boolean} [markdownPaste] - Convert pasted Markdown text to HTML (default: true)\n * @property {boolean} [readOnly] - Start editor in read-only / non-editable mode\n * @property {boolean} [spellcheck] - Enable browser spellcheck in the editable area (default: true)\n * @property {string} [direction] - Text direction: 'ltr' (default) | 'rtl'\n * @property {string} [toolbarOverflow] - Toolbar overflow strategy: 'wrap' (default) | 'scroll'\n * @property {boolean} [autoSave] - Auto-save content to localStorage on change\n * @property {string} [autoSaveKey] - localStorage key used for auto-save (default: 'autumnnote-autosave')\n * @property {number} [maxChars] - Maximum character count (0 = unlimited). Shows warning in statusbar.\n * @property {number} [maxWords] - Maximum word count (0 = unlimited). Shows warning in statusbar.\n * @property {boolean} [tableHeaderRow] - Insert a header row (<thead><th>) when creating tables\n * @property {Function} [onPaste] - Callback fired on every paste: ({ text, html }) => void\n * @property {Function} [onSelectionChange] - Callback fired on cursor/selection change: (context) => void\n * @property {string[]} [colorSwatches] - Custom brand colour swatches prepended to the colour-picker palette\n * @property {Function} [onDestroy] - Callback fired when the editor is destroyed: (context) => void\n * @property {Function} [onCharLimitReached] - Callback fired when the character limit is hit: (context) => void\n * @property {Function} [onWordLimitReached] - Callback fired when the word limit is hit: (context) => void\n * @property {string} [focusColor] - Custom focus ring colour, e.g. '#f97316'. Overrides the default blue.\n */\n\n/** @type {AsnOptions} */\nexport const defaultOptions = {\n placeholder: '',\n height: 200,\n minHeight: 100,\n maxHeight: 0,\n focus: false,\n resizable: true,\n toolbar: defaultToolbar,\n // UI integration options\n // If `useBootstrap` is true, toolbar buttons will use the Bootstrap button classes\n // (set `toolbarButtonClass` to customize). Works with Bootstrap 4 and 5.\n useBootstrap: false,\n toolbarButtonClass: 'btn btn-sm btn-light',\n // Icon options — uses Font Awesome by default. Consumers must include Font Awesome CSS.\n useFontAwesome: true,\n // Default FontAwesome prefix — 'fas' for FA5, 'fa-solid' for FA6. Change if needed.\n fontAwesomeClass: 'fas',\n pasteAsPlainText: false,\n pasteCleanHTML: true,\n pasteStripAttributes: false,\n allowImageUpload: true,\n maxImageSize: 5,\n tabSize: 4,\n onChange: null,\n onFocus: null,\n onBlur: null,\n onInit: null,\n onImageUpload: null,\n onImageError: null,\n stickyToolbar: false,\n stickyToolbarOffset: 0,\n theme: 'light',\n codeHighlight: true,\n codeHighlightCDN: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0',\n markdownPaste: true,\n historyLimit: 100,\n // Default font family applied to the editor and shown in the dropdown when no explicit font is set\n defaultFontFamily: 'Arial',\n // Default font size applied to the editor and shown in the size dropdown when no explicit size is set\n defaultFontSize: '14px',\n // Font families shown in the toolbar font-family dropdown\n fontFamilies: [\n 'Arial',\n 'Arial Black',\n 'Comic Sans MS',\n 'Courier New',\n 'Georgia',\n 'Impact',\n 'Tahoma',\n 'Times New Roman',\n 'Trebuchet MS',\n 'Verdana',\n ],\n // Read-only mode — disables all editing when true\n readOnly: false,\n // Enable/disable browser spell-check on the editable area\n spellcheck: true,\n // Text direction: 'ltr' (default) or 'rtl'\n direction: 'ltr',\n // How the toolbar handles overflow: 'wrap' (default, wraps to next line) or 'scroll' (single scrollable row)\n toolbarOverflow: 'wrap',\n // Auto-save content to localStorage on every change\n autoSave: false,\n // localStorage key used when autoSave is enabled\n autoSaveKey: 'autumnnote-autosave',\n // Maximum character count (0 = unlimited)\n maxChars: 0,\n // Maximum word count (0 = unlimited)\n maxWords: 0,\n // Insert a header row (<thead>) when creating new tables\n tableHeaderRow: false,\n // Callback fired on every cursor/selection change inside the editor\n onSelectionChange: null,\n // Custom brand colour swatches to prepend to the toolbar colour-picker palette\n colorSwatches: [],\n // Callback fired after a paste event: function({ text, html })\n onPaste: null,\n // Callback fired just before the editor instance is destroyed\n onDestroy: null,\n // Callback fired when the character limit is reached: function(context)\n onCharLimitReached: null,\n // Callback fired when the word limit is reached: function(context)\n onWordLimitReached: null,\n // Custom focus ring colour — overrides the default blue when set.\n // Accepts any valid CSS colour string, e.g. '#f97316', 'hsl(25,90%,55%)'.\n focusColor: null,\n // Display language for the editor UI.\n // Built-in values: 'en' (default), 'vi', 'ja', 'zh', 'fr'.\n // Pass a partial or full locale object to override individual strings.\n lang: 'en',\n};\n","/**\n * en.js - English locale (canonical reference)\n * All other locales deep-merge against this to fill missing keys.\n */\n\n/** @type {import('../../../types/index.js').AsnLocale} */\nexport const en = {\n toolbar: {\n bold: 'Bold (Ctrl+B)',\n italic: 'Italic (Ctrl+I)',\n underline: 'Underline (Ctrl+U)',\n strikethrough: 'Strikethrough',\n superscript: 'Superscript',\n subscript: 'Subscript',\n alignLeft: 'Align Left',\n alignCenter: 'Align Center',\n alignRight: 'Align Right',\n alignJustify: 'Justify',\n ul: 'Unordered List',\n ol: 'Ordered List',\n checklist: 'Checklist',\n indent: 'Indent',\n outdent: 'Outdent',\n undo: 'Undo (Ctrl+Z)',\n redo: 'Redo (Ctrl+Y)',\n hr: 'Horizontal Rule',\n link: 'Insert Link',\n image: 'Insert Image',\n video: 'Insert Video',\n emoji: 'Insert Emoji',\n icon: 'Insert FA Icon',\n table: 'Insert Table',\n fontSize: 'Font Size',\n fontSizePlaceholder: 'Size',\n removeFormat: 'Remove Format',\n direction: 'Toggle Text Direction (LTR / RTL)',\n fontFamily: 'Font Family',\n paragraphStyle: 'Paragraph Style',\n paragraphStylePlaceholder: 'Style',\n lineHeight: 'Line Height',\n lineHeightPlaceholder: '\\u2195 Line',\n codeview: 'HTML Code View',\n fullscreen: 'Fullscreen',\n shortcuts: 'Keyboard Shortcuts (Ctrl+Shift+/)',\n find: 'Find (Ctrl+F)',\n findReplace: 'Find & Replace (Ctrl+H)',\n inlineCode: 'Inline Code (Ctrl+`)',\n print: 'Print',\n foreColor: 'Text Color',\n backColor: 'Highlight Color',\n chooseTextColor: 'Choose text color',\n chooseHighlightColor: 'Choose highlight color',\n customColor: 'Custom color',\n insertTableLabel: 'Insert Table',\n /** Map of paragraph-style value → label (only values needing translation) */\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Quote',\n pre: 'Code',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Insert link',\n title: 'Insert Link',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Display Text',\n textPlaceholder: 'Link text',\n openInNewTab: 'Open in new tab',\n insertBtn: 'Insert',\n cancelBtn: 'Cancel',\n },\n\n imageDialog: {\n ariaLabel: 'Insert image',\n title: 'Insert Image',\n imageUrl: 'Image URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Alt Text',\n altPlaceholder: 'Describe the image',\n alignment: 'Alignment',\n alignNone: 'None',\n alignLeft: 'Left',\n alignCenter: 'Center',\n alignRight: 'Right',\n uploadLabel: 'Or upload a file',\n insertBtn: 'Insert',\n cancelBtn: 'Cancel',\n },\n\n videoDialog: {\n ariaLabel: 'Insert video',\n title: 'Insert Video',\n videoUrl: 'Video URL',\n urlPlaceholder: 'YouTube, Vimeo, or direct .mp4 URL',\n widthLabel: 'Width (px)',\n widthPlaceholder: '560',\n insertBtn: 'Insert',\n cancelBtn: 'Cancel',\n /** @param {string} type */\n detected: (type) => `Detected: ${type}`,\n unknownFormat: 'Unknown format \\u2014 will try direct video embed',\n invalidUrl: 'Invalid URL \\u2014 please enter a valid video link.',\n },\n\n emojiDialog: {\n ariaLabel: 'Insert emoji',\n title: 'Insert Emoji',\n searchPlaceholder: 'Search emojis\\u2026',\n all: 'All',\n cancelBtn: 'Cancel',\n close: 'Close',\n categories: {\n smileys: 'Smileys',\n people: 'People',\n animals: 'Animals',\n food: 'Food',\n travel: 'Travel',\n objects: 'Objects',\n symbols: 'Symbols',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Insert FA icon',\n title: 'Insert FA Icon',\n searchPlaceholder: 'Search icons\\u2026',\n all: 'All',\n style: 'Style',\n size: 'Size',\n color: 'Color',\n useColor: ' Use color',\n selectHint: 'Select an icon',\n insertBtn: 'Insert FA Icon',\n cancelBtn: 'Cancel',\n close: 'Close',\n categories: {\n popular: 'Popular',\n interface: 'Interface',\n navigation: 'Navigation',\n media: 'Media',\n communication: 'Communication',\n files: 'Files',\n people: 'People',\n objects: 'Objects',\n },\n },\n\n findReplace: {\n findTitle: 'Find',\n findReplaceTitle: 'Find & Replace',\n findPlaceholder: 'Find\\u2026',\n searchAriaLabel: 'Search text',\n caseSensitive: '\\u00a0Case sensitive',\n prevBtn: '\\u2190 Prev',\n nextBtn: 'Next \\u2192',\n replacePlaceholder: 'Replace with\\u2026',\n replaceAriaLabel: 'Replace with',\n replaceBtn: 'Replace',\n replaceAllBtn: 'Replace All',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'Keyboard Shortcuts',\n ariaLabel: 'Keyboard Shortcuts',\n close: 'Close',\n shortcuts: [\n {\n category: 'Text Formatting',\n items: [\n { keys: 'Ctrl + B', action: 'Bold' },\n { keys: 'Ctrl + I', action: 'Italic' },\n { keys: 'Ctrl + U', action: 'Underline' },\n { keys: 'Ctrl + K', action: 'Insert / edit link' },\n ],\n },\n {\n category: 'History',\n items: [\n { keys: 'Ctrl + Z', action: 'Undo' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Redo' },\n ],\n },\n {\n category: 'Selection & Navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Select all content' },\n { keys: 'Tab', action: 'Indent list item / insert spaces' },\n { keys: 'Shift + Tab', action: 'Outdent list item' },\n ],\n },\n {\n category: 'Clipboard',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Paste as plain text' },\n ],\n },\n {\n category: 'Find & Replace',\n items: [\n { keys: 'Ctrl + F', action: 'Find in document' },\n { keys: 'Ctrl + H', action: 'Find & Replace' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Show this keyboard shortcuts dialog' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Cut',\n copy: 'Copy',\n paste: 'Paste',\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n textColor: 'Text Color',\n highlightColor: 'Highlight Color',\n copyFormat: 'Copy Format',\n pasteFormat: 'Paste Format',\n removeFormat: 'Remove Format',\n link: 'Insert Link',\n image: 'Insert Image',\n video: 'Insert Video',\n table: 'Insert Table',\n back: 'Back',\n noHighlight: 'No highlight',\n customColor: 'Custom color',\n customColorLabel: 'Custom\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'Resize editor',\n /** @param {number} n */\n words: (n) => `Words: ${n}`,\n /** @param {number} n @param {number} max */\n wordsLimit: (n, max) => `Words: ${n}/${max}`,\n /** @param {number} n */\n chars: (n) => `Chars: ${n}`,\n /** @param {number} n @param {number} max */\n charsLimit: (n, max) => `Chars: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Link actions',\n openLink: 'Open link',\n copyUrl: 'Copy URL',\n editLink: 'Edit link',\n removeLink: 'Remove link',\n },\n image: {\n ariaLabel: 'Image actions',\n label: 'Image',\n floatLeft: 'Float Left',\n noFloat: 'No Float',\n alignCenter: 'Align Center',\n floatRight: 'Float Right',\n originalSize: 'Original Size',\n rotateLeft: 'Rotate Left',\n rotateRight: 'Rotate Right',\n cropImage: 'Crop Image',\n addCaption: 'Add / Edit Caption',\n deleteImage: 'Delete Image',\n },\n code: {\n ariaLabel: 'Code block actions',\n label: 'Code',\n syntaxLanguage: 'Syntax Language',\n syntaxAriaLabel: 'Syntax language',\n copyCode: 'Copy Code',\n toggleWordWrap: 'Toggle Word Wrap',\n enableWordWrap: 'Enable Word Wrap',\n disableWordWrap: 'Disable Word Wrap',\n convertToParagraph: 'Convert to Paragraph',\n deleteCodeBlock: 'Delete Code Block',\n },\n table: {\n ariaLabel: 'Table actions',\n label: 'Table',\n selectCells: 'Select Cells',\n addRowAbove: 'Add Row Above',\n addRowBelow: 'Add Row Below',\n deleteRow: 'Delete Row',\n addColumnLeft: 'Add Column Left',\n addColumnRight: 'Add Column Right',\n deleteColumn: 'Delete Column',\n mergeCells: 'Merge Cells',\n unmergeCells: 'Unmerge Cells',\n columnWidth: 'Column Width',\n rowHeight: 'Row Height',\n tableBorderWidth: 'Table Border Width',\n deleteTable: 'Delete Table',\n columnWidthPx: 'Column Width (px)',\n rowHeightPx: 'Row Height (px)',\n tableBorderWidthPx: 'Table Border Width (px)',\n cancelBtn: 'Cancel',\n applyBtn: 'Apply',\n },\n video: {\n ariaLabel: 'Video actions',\n label: 'Video',\n floatLeft: 'Float Left',\n noFloat: 'No Float',\n alignCenter: 'Align Center',\n floatRight: 'Float Right',\n originalSize: 'Original Size',\n previewVideo: 'Preview Video',\n exitPreview: 'Exit Preview',\n deleteVideo: 'Delete Video',\n },\n },\n\n errors: {\n /** @param {string} type */\n imageFormat: (type) =>\n `Format \"${type}\" is not supported for display in web browsers. Please convert to JPEG, PNG, or WebP first.`,\n /** @param {number} maxSize */\n imageSize: (maxSize) =>\n `Image file is too large. Maximum allowed size is ${maxSize} MB.`,\n },\n};\n","/**\n * vi.js - Tiếng Việt locale\n * Chỉ cần khai báo các key khác với tiếng Anh (en.js).\n * Các key còn lại sẽ được lấy từ en.js qua deep-merge.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const vi = {\n toolbar: {\n bold: 'Đậm (Ctrl+B)',\n italic: 'Nghiêng (Ctrl+I)',\n underline: 'Gạch chân (Ctrl+U)',\n strikethrough: 'Gạch ngang',\n superscript: 'Chỉ số trên',\n subscript: 'Chỉ số dưới',\n alignLeft: 'Căn trái',\n alignCenter: 'Căn giữa',\n alignRight: 'Căn phải',\n alignJustify: 'Căn đều',\n ul: 'Danh sách không thứ tự',\n ol: 'Danh sách có thứ tự',\n checklist: 'Danh sách kiểm tra',\n indent: 'Tăng thụt đầu dòng',\n outdent: 'Giảm thụt đầu dòng',\n undo: 'Hoàn tác (Ctrl+Z)',\n redo: 'Làm lại (Ctrl+Y)',\n hr: 'Đường kẻ ngang',\n link: 'Chèn liên kết',\n image: 'Chèn hình ảnh',\n video: 'Chèn video',\n emoji: 'Chèn biểu tượng cảm xúc',\n icon: 'Chèn biểu tượng FA',\n table: 'Chèn bảng',\n fontSize: 'Cỡ chữ',\n fontSizePlaceholder: 'Cỡ',\n removeFormat: 'Xóa định dạng',\n direction: 'Chuyển hướng văn bản (LTR / RTL)',\n fontFamily: 'Phông chữ',\n paragraphStyle: 'Kiểu đoạn văn',\n paragraphStylePlaceholder: 'Kiểu',\n lineHeight: 'Khoảng cách dòng',\n lineHeightPlaceholder: '\\u2195 Dòng',\n codeview: 'Xem mã HTML',\n fullscreen: 'Toàn màn hình',\n shortcuts: 'Phím tắt (Ctrl+Shift+/)',\n find: 'Tìm kiếm (Ctrl+F)',\n findReplace: 'Tìm & Thay thế (Ctrl+H)',\n inlineCode: 'Mã nội tuyến (Ctrl+`)',\n print: 'In',\n foreColor: 'Màu chữ',\n backColor: 'Màu nền chữ',\n chooseTextColor: 'Chọn màu chữ',\n chooseHighlightColor: 'Chọn màu nền',\n customColor: 'Màu tùy chỉnh',\n insertTableLabel: 'Chèn bảng',\n paragraphItems: {\n p: 'Bình thường',\n blockquote: 'Trích dẫn',\n pre: 'Mã',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Chèn liên kết',\n title: 'Chèn liên kết',\n url: 'Địa chỉ URL',\n urlPlaceholder: 'https://',\n displayText: 'Văn bản hiển thị',\n textPlaceholder: 'Nội dung liên kết',\n openInNewTab: 'Mở trong tab mới',\n insertBtn: 'Chèn',\n cancelBtn: 'Hủy',\n },\n\n imageDialog: {\n ariaLabel: 'Chèn hình ảnh',\n title: 'Chèn hình ảnh',\n imageUrl: 'URL hình ảnh',\n urlPlaceholder: 'https://example.com/anh.png',\n altText: 'Văn bản thay thế',\n altPlaceholder: 'Mô tả hình ảnh',\n alignment: 'Căn chỉnh',\n alignNone: 'Không',\n alignLeft: 'Trái',\n alignCenter: 'Giữa',\n alignRight: 'Phải',\n uploadLabel: 'Hoặc tải lên tệp',\n insertBtn: 'Chèn',\n cancelBtn: 'Hủy',\n },\n\n videoDialog: {\n ariaLabel: 'Chèn video',\n title: 'Chèn video',\n videoUrl: 'URL video',\n urlPlaceholder: 'YouTube, Vimeo, hoặc URL .mp4 trực tiếp',\n widthLabel: 'Chiều rộng (px)',\n widthPlaceholder: '560',\n insertBtn: 'Chèn',\n cancelBtn: 'Hủy',\n detected: (type) => `Đã phát hiện: ${type}`,\n unknownFormat: 'Định dạng không xác định \\u2014 sẽ thử nhúng video trực tiếp',\n invalidUrl: 'URL không hợp lệ \\u2014 vui lòng nhập đường dẫn video hợp lệ.',\n },\n\n emojiDialog: {\n ariaLabel: 'Chèn biểu tượng cảm xúc',\n title: 'Chèn biểu tượng cảm xúc',\n searchPlaceholder: 'Tìm kiếm biểu tượng\\u2026',\n all: 'Tất cả',\n cancelBtn: 'Hủy',\n close: 'Đóng',\n categories: {\n smileys: 'Mặt cười',\n people: 'Con người',\n animals: 'Động vật',\n food: 'Thức ăn',\n travel: 'Du lịch',\n objects: 'Đồ vật',\n symbols: 'Ký hiệu',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Chèn biểu tượng FA',\n title: 'Chèn biểu tượng FA',\n searchPlaceholder: 'Tìm kiếm biểu tượng\\u2026',\n all: 'Tất cả',\n style: 'Kiểu',\n size: 'Kích thước',\n color: 'Màu sắc',\n useColor: ' Dùng màu',\n selectHint: 'Chọn một biểu tượng',\n insertBtn: 'Chèn biểu tượng FA',\n cancelBtn: 'Hủy',\n close: 'Đóng',\n categories: {\n popular: 'Phổ biến',\n interface: 'Giao diện',\n navigation: 'Điều hướng',\n media: 'Phương tiện',\n communication: 'Liên lạc',\n files: 'Tệp tin',\n people: 'Con người',\n objects: 'Đồ vật',\n },\n },\n\n findReplace: {\n findTitle: 'Tìm kiếm',\n findReplaceTitle: 'Tìm & Thay thế',\n findPlaceholder: 'Tìm\\u2026',\n searchAriaLabel: 'Văn bản tìm kiếm',\n caseSensitive: '\\u00a0Phân biệt hoa thường',\n prevBtn: '\\u2190 Trước',\n nextBtn: 'Tiếp \\u2192',\n replacePlaceholder: 'Thay thế bằng\\u2026',\n replaceAriaLabel: 'Thay thế bằng',\n replaceBtn: 'Thay thế',\n replaceAllBtn: 'Thay thế tất cả',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'Phím tắt bàn phím',\n ariaLabel: 'Phím tắt bàn phím',\n close: 'Đóng',\n shortcuts: [\n {\n category: 'Định dạng văn bản',\n items: [\n { keys: 'Ctrl + B', action: 'Đậm' },\n { keys: 'Ctrl + I', action: 'Nghiêng' },\n { keys: 'Ctrl + U', action: 'Gạch chân' },\n { keys: 'Ctrl + K', action: 'Chèn / sửa liên kết' },\n ],\n },\n {\n category: 'Lịch sử',\n items: [\n { keys: 'Ctrl + Z', action: 'Hoàn tác' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Làm lại' },\n ],\n },\n {\n category: 'Chọn & Điều hướng',\n items: [\n { keys: 'Ctrl + A', action: 'Chọn tất cả' },\n { keys: 'Tab', action: 'Tăng thụt đầu dòng / chèn khoảng trắng' },\n { keys: 'Shift + Tab', action: 'Giảm thụt đầu dòng' },\n ],\n },\n {\n category: 'Bảng nhớ tạm',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Dán dưới dạng văn bản thuần' },\n ],\n },\n {\n category: 'Tìm & Thay thế',\n items: [\n { keys: 'Ctrl + F', action: 'Tìm trong tài liệu' },\n { keys: 'Ctrl + H', action: 'Tìm & Thay thế' },\n ],\n },\n {\n category: 'Trình soạn thảo',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Hiện hộp thoại phím tắt' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Cắt',\n copy: 'Sao chép',\n paste: 'Dán',\n bold: 'Đậm',\n italic: 'Nghiêng',\n underline: 'Gạch chân',\n textColor: 'Màu chữ',\n highlightColor: 'Màu nền chữ',\n copyFormat: 'Sao chép định dạng',\n pasteFormat: 'Dán định dạng',\n removeFormat: 'Xóa định dạng',\n link: 'Chèn liên kết',\n image: 'Chèn hình ảnh',\n video: 'Chèn video',\n table: 'Chèn bảng',\n back: 'Quay lại',\n noHighlight: 'Không tô màu',\n customColor: 'Màu tùy chỉnh',\n customColorLabel: 'Tùy ch\\u1ec9nh\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'Kéo để thay đổi kích thước',\n words: (n) => `Từ: ${n}`,\n wordsLimit: (n, max) => `Từ: ${n}/${max}`,\n chars: (n) => `Ký tự: ${n}`,\n charsLimit: (n, max) => `Ký tự: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Hành động liên kết',\n openLink: 'Mở liên kết',\n copyUrl: 'Sao chép URL',\n editLink: 'Sửa liên kết',\n removeLink: 'Xóa liên kết',\n },\n image: {\n ariaLabel: 'Hành động hình ảnh',\n label: 'Hình ảnh',\n floatLeft: 'Nổi trái',\n noFloat: 'Không nổi',\n alignCenter: 'Căn giữa',\n floatRight: 'Nổi phải',\n originalSize: 'Kích thước gốc',\n rotateLeft: 'Xoay trái',\n rotateRight: 'Xoay phải',\n cropImage: 'Cắt ảnh',\n addCaption: 'Thêm / Sửa chú thích',\n deleteImage: 'Xóa hình ảnh',\n },\n code: {\n ariaLabel: 'Hành động khối mã',\n label: 'Mã',\n syntaxLanguage: 'Ngôn ngữ cú pháp',\n syntaxAriaLabel: 'Ngôn ngữ cú pháp',\n copyCode: 'Sao chép mã',\n toggleWordWrap: 'Chuyển đổi xuống dòng',\n enableWordWrap: 'Bật xuống dòng',\n disableWordWrap: 'Tắt xuống dòng',\n convertToParagraph: 'Chuyển thành đoạn văn',\n deleteCodeBlock: 'Xóa khối mã',\n },\n table: {\n ariaLabel: 'Hành động bảng',\n label: 'Bảng',\n selectCells: 'Chọn ô',\n addRowAbove: 'Thêm hàng phía trên',\n addRowBelow: 'Thêm hàng phía dưới',\n deleteRow: 'Xóa hàng',\n addColumnLeft: 'Thêm cột bên trái',\n addColumnRight: 'Thêm cột bên phải',\n deleteColumn: 'Xóa cột',\n mergeCells: 'Gộp ô',\n unmergeCells: 'Tách ô',\n columnWidth: 'Chiều rộng cột',\n rowHeight: 'Chiều cao hàng',\n tableBorderWidth: 'Độ rộng viền bảng',\n deleteTable: 'Xóa bảng',\n columnWidthPx: 'Chiều rộng cột (px)',\n rowHeightPx: 'Chiều cao hàng (px)',\n tableBorderWidthPx: 'Độ rộng viền bảng (px)',\n cancelBtn: 'Hủy',\n applyBtn: 'Áp dụng',\n },\n video: {\n ariaLabel: 'Hành động video',\n label: 'Video',\n floatLeft: 'Nổi trái',\n noFloat: 'Không nổi',\n alignCenter: 'Căn giữa',\n floatRight: 'Nổi phải',\n originalSize: 'Kích thước gốc',\n previewVideo: 'Xem trước',\n exitPreview: 'Thoát xem trước',\n deleteVideo: 'Xóa video',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `Định dạng \"${type}\" không được hỗ trợ hiển thị trên trình duyệt. Vui lòng chuyển đổi sang JPEG, PNG hoặc WebP.`,\n imageSize: (maxSize) =>\n `Tệp hình ảnh quá lớn. Kích thước tối đa cho phép là ${maxSize} MB.`,\n },\n};\n","/**\n * ja.js - 日本語ロケール (Japanese)\n * en.js をベースに上書きするキーのみ定義します。\n * 未定義のキーは resolveLocale による deep-merge で en.js から補完されます。\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const ja = {\n toolbar: {\n bold: '太字 (Ctrl+B)',\n italic: '斜体 (Ctrl+I)',\n underline: '下線 (Ctrl+U)',\n strikethrough: '取り消し線',\n superscript: '上付き文字',\n subscript: '下付き文字',\n alignLeft: '左揃え',\n alignCenter: '中央揃え',\n alignRight: '右揃え',\n alignJustify: '両端揃え',\n ul: '箇条書きリスト',\n ol: '番号付きリスト',\n checklist: 'チェックリスト',\n indent: 'インデントを増やす',\n outdent: 'インデントを減らす',\n undo: '元に戻す (Ctrl+Z)',\n redo: 'やり直す (Ctrl+Y)',\n hr: '水平線',\n link: 'リンクを挿入',\n image: '画像を挿入',\n video: '動画を挿入',\n emoji: '絵文字を挿入',\n icon: 'FAアイコンを挿入',\n table: 'テーブルを挿入',\n fontSize: 'フォントサイズ',\n fontSizePlaceholder: 'サイズ',\n removeFormat: '書式をリセット',\n direction: '文字方向を切り替え (LTR / RTL)',\n fontFamily: 'フォント',\n paragraphStyle: '段落スタイル',\n paragraphStylePlaceholder: 'スタイル',\n lineHeight: '行の高さ',\n lineHeightPlaceholder: '\\u2195 行間',\n codeview: 'HTMLソースを表示',\n fullscreen: '全画面表示',\n shortcuts: 'キーボードショートカット (Ctrl+Shift+/)',\n find: '検索 (Ctrl+F)',\n findReplace: '検索と置換 (Ctrl+H)',\n inlineCode: 'インラインコード (Ctrl+`)',\n print: '印刷',\n foreColor: '文字色',\n backColor: 'ハイライト色',\n chooseTextColor: '文字色を選択',\n chooseHighlightColor: 'ハイライト色を選択',\n customColor: 'カスタムカラー',\n insertTableLabel: 'テーブルを挿入',\n paragraphItems: {\n p: '標準',\n blockquote: '引用',\n pre: 'コード',\n },\n },\n\n linkDialog: {\n ariaLabel: 'リンクを挿入',\n title: 'リンクを挿入',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: '表示テキスト',\n textPlaceholder: 'リンクテキスト',\n openInNewTab: '新しいタブで開く',\n insertBtn: '挿入',\n cancelBtn: 'キャンセル',\n },\n\n imageDialog: {\n ariaLabel: '画像を挿入',\n title: '画像を挿入',\n imageUrl: '画像URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: '代替テキスト',\n altPlaceholder: '画像の説明',\n alignment: '配置',\n alignNone: 'なし',\n alignLeft: '左',\n alignCenter: '中央',\n alignRight: '右',\n uploadLabel: 'ファイルをアップロード',\n insertBtn: '挿入',\n cancelBtn: 'キャンセル',\n },\n\n videoDialog: {\n ariaLabel: '動画を挿入',\n title: '動画を挿入',\n videoUrl: '動画URL',\n urlPlaceholder: 'YouTube、Vimeo、または直接動画URL',\n widthLabel: '幅 (px)',\n widthPlaceholder: '560',\n insertBtn: '挿入',\n cancelBtn: 'キャンセル',\n detected: (type) => `検出: ${type}`,\n unknownFormat: '不明な形式 \\u2014 直接動画埋め込みを試みます',\n invalidUrl: 'URLが無効です \\u2014 有効な動画URLを入力してください。',\n },\n\n emojiDialog: {\n ariaLabel: '絵文字を挿入',\n title: '絵文字を挿入',\n searchPlaceholder: '絵文字を検索\\u2026',\n all: 'すべて',\n cancelBtn: 'キャンセル',\n close: '閉じる',\n categories: {\n smileys: '顔文字',\n people: '人物',\n animals: '動物',\n food: '食べ物',\n travel: '旅行',\n objects: 'モノ',\n symbols: '記号',\n },\n },\n\n iconDialog: {\n ariaLabel: 'FAアイコンを挿入',\n title: 'FAアイコンを挿入',\n searchPlaceholder: 'アイコンを検索\\u2026',\n all: 'すべて',\n style: 'スタイル',\n size: 'サイズ',\n color: 'カラー',\n useColor: ' カラーを使用',\n selectHint: 'アイコンを選択してください',\n insertBtn: 'FAアイコンを挿入',\n cancelBtn: 'キャンセル',\n close: '閉じる',\n categories: {\n popular: '人気',\n interface: 'インターフェース',\n navigation: 'ナビゲーション',\n media: 'メディア',\n communication: '通信',\n files: 'ファイル',\n people: '人物',\n objects: 'モノ',\n },\n },\n\n findReplace: {\n findTitle: '検索',\n findReplaceTitle: '検索と置換',\n findPlaceholder: '検索\\u2026',\n searchAriaLabel: '検索テキスト',\n caseSensitive: '\\u00a0大文字/小文字を区別',\n prevBtn: '\\u2190 前へ',\n nextBtn: '次へ \\u2192',\n replacePlaceholder: '置換後\\u2026',\n replaceAriaLabel: '置換後のテキスト',\n replaceBtn: '置換',\n replaceAllBtn: 'すべて置換',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'キーボードショートカット',\n ariaLabel: 'キーボードショートカット',\n close: '閉じる',\n shortcuts: [\n {\n category: 'テキスト書式',\n items: [\n { keys: 'Ctrl + B', action: '太字' },\n { keys: 'Ctrl + I', action: '斜体' },\n { keys: 'Ctrl + U', action: '下線' },\n { keys: 'Ctrl + K', action: 'リンクの挿入 / 編集' },\n ],\n },\n {\n category: '履歴',\n items: [\n { keys: 'Ctrl + Z', action: '元に戻す' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'やり直す' },\n ],\n },\n {\n category: '選択と移動',\n items: [\n { keys: 'Ctrl + A', action: 'すべて選択' },\n { keys: 'Tab', action: 'インデント増加 / スペース挿入' },\n { keys: 'Shift + Tab', action: 'インデント減少' },\n ],\n },\n {\n category: 'クリップボード',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'プレーンテキストとして貼り付け' },\n ],\n },\n {\n category: '検索と置換',\n items: [\n { keys: 'Ctrl + F', action: '文書内を検索' },\n { keys: 'Ctrl + H', action: '検索と置換' },\n ],\n },\n {\n category: 'エディター',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'ショートカットダイアログを表示' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: '切り取り',\n copy: 'コピー',\n paste: '貼り付け',\n bold: '太字',\n italic: '斜体',\n underline: '下線',\n textColor: '文字色',\n highlightColor: 'ハイライト色',\n copyFormat: '書式をコピー',\n pasteFormat: '書式を貼り付け',\n removeFormat: '書式をリセット',\n link: 'リンクを挿入',\n image: '画像を挿入',\n video: '動画を挿入',\n table: 'テーブルを挿入',\n back: '戻る',\n noHighlight: 'ハイライトなし',\n customColor: 'カスタムカラー',\n customColorLabel: 'カスタム\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'ドラッグしてリサイズ',\n words: (n) => `単語数: ${n}`,\n wordsLimit: (n, max) => `単語数: ${n}/${max}`,\n chars: (n) => `文字数: ${n}`,\n charsLimit: (n, max) => `文字数: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'リンク操作',\n openLink: 'リンクを開く',\n copyUrl: 'URLをコピー',\n editLink: 'リンクを編集',\n removeLink: 'リンクを削除',\n },\n image: {\n ariaLabel: '画像操作',\n label: '画像',\n floatLeft: '左に回り込み',\n noFloat: '回り込みなし',\n alignCenter: '中央揃え',\n floatRight: '右に回り込み',\n originalSize: '元のサイズ',\n rotateLeft: '左に回転',\n rotateRight: '右に回転',\n cropImage: '画像をトリミング',\n addCaption: 'キャプションを追加 / 編集',\n deleteImage: '画像を削除',\n },\n code: {\n ariaLabel: 'コードブロック操作',\n label: 'コード',\n syntaxLanguage: '言語',\n syntaxAriaLabel: '構文言語',\n copyCode: 'コードをコピー',\n toggleWordWrap: '折り返しを切り替え',\n enableWordWrap: '折り返しを有効にする',\n disableWordWrap: '折り返しを無効にする',\n convertToParagraph: '段落に変換',\n deleteCodeBlock: 'コードブロックを削除',\n },\n table: {\n ariaLabel: 'テーブル操作',\n label: 'テーブル',\n selectCells: 'セルを選択',\n addRowAbove: '上に行を追加',\n addRowBelow: '下に行を追加',\n deleteRow: '行を削除',\n addColumnLeft: '左に列を追加',\n addColumnRight: '右に列を追加',\n deleteColumn: '列を削除',\n mergeCells: 'セルを結合',\n unmergeCells: 'セルの結合を解除',\n columnWidth: '列幅',\n rowHeight: '行の高さ',\n tableBorderWidth: 'テーブルの枠幅',\n deleteTable: 'テーブルを削除',\n columnWidthPx: '列幅 (px)',\n rowHeightPx: '行の高さ (px)',\n tableBorderWidthPx: 'テーブルの枠幅 (px)',\n cancelBtn: 'キャンセル',\n applyBtn: '適用',\n },\n video: {\n ariaLabel: '動画操作',\n label: '動画',\n floatLeft: '左に回り込み',\n noFloat: '回り込みなし',\n alignCenter: '中央揃え',\n floatRight: '右に回り込み',\n originalSize: '元のサイズ',\n previewVideo: 'プレビュー',\n exitPreview: 'プレビューを終了',\n deleteVideo: '動画を削除',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `形式 \"${type}\" はブラウザでの表示をサポートしていません。JPEG、PNG、または WebP に変換してください。`,\n imageSize: (maxSize) =>\n `画像ファイルが大きすぎます。最大許容サイズは ${maxSize} MB です。`,\n },\n};\n","/**\n * zh.js - 简体中文 (Simplified Chinese) locale\n * 仅包含与 en.js 不同的键值。\n * resolveLocale 会将本文件与 en.js 进行深度合并。\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const zh = {\n toolbar: {\n bold: '粗体 (Ctrl+B)',\n italic: '斜体 (Ctrl+I)',\n underline: '下划线 (Ctrl+U)',\n strikethrough: '删除线',\n superscript: '上标',\n subscript: '下标',\n alignLeft: '左对齐',\n alignCenter: '居中',\n alignRight: '右对齐',\n alignJustify: '两端对齐',\n ul: '无序列表',\n ol: '有序列表',\n checklist: '待办列表',\n indent: '增加缩进',\n outdent: '减少缩进',\n undo: '撤销 (Ctrl+Z)',\n redo: '重做 (Ctrl+Y)',\n hr: '水平分割线',\n link: '插入链接',\n image: '插入图片',\n video: '插入视频',\n emoji: '插入表情',\n icon: '插入 FA 图标',\n table: '插入表格',\n fontSize: '字号',\n fontSizePlaceholder: '大小',\n removeFormat: '清除格式',\n direction: '切换文字方向 (LTR / RTL)',\n fontFamily: '字体',\n paragraphStyle: '段落样式',\n paragraphStylePlaceholder: '样式',\n lineHeight: '行高',\n lineHeightPlaceholder: '\\u2195 行距',\n codeview: '查看 HTML 源码',\n fullscreen: '全屏',\n shortcuts: '键盘快捷键 (Ctrl+Shift+/)',\n find: '搜索 (Ctrl+F)',\n findReplace: '查找和替换 (Ctrl+H)',\n inlineCode: '行内代码 (Ctrl+`)',\n print: '打印',\n foreColor: '文字颜色',\n backColor: '高亮颜色',\n chooseTextColor: '选择文字颜色',\n chooseHighlightColor: '选择高亮颜色',\n customColor: '自定义颜色',\n insertTableLabel: '插入表格',\n paragraphItems: {\n p: '正文',\n blockquote: '引用',\n pre: '代码',\n },\n },\n\n linkDialog: {\n ariaLabel: '插入链接',\n title: '插入链接',\n url: '链接地址',\n urlPlaceholder: 'https://',\n displayText: '显示文字',\n textPlaceholder: '链接文字',\n openInNewTab: '在新标签页中打开',\n insertBtn: '插入',\n cancelBtn: '取消',\n },\n\n imageDialog: {\n ariaLabel: '插入图片',\n title: '插入图片',\n imageUrl: '图片地址',\n urlPlaceholder: 'https://example.com/image.png',\n altText: '替代文字',\n altPlaceholder: '图片描述',\n alignment: '对齐方式',\n alignNone: '无',\n alignLeft: '左',\n alignCenter: '居中',\n alignRight: '右',\n uploadLabel: '或上传文件',\n insertBtn: '插入',\n cancelBtn: '取消',\n },\n\n videoDialog: {\n ariaLabel: '插入视频',\n title: '插入视频',\n videoUrl: '视频地址',\n urlPlaceholder: 'YouTube、Vimeo 或直接 .mp4 链接',\n widthLabel: '宽度 (px)',\n widthPlaceholder: '560',\n insertBtn: '插入',\n cancelBtn: '取消',\n detected: (type) => `已识别: ${type}`,\n unknownFormat: '未知格式 \\u2014 将尝试直接嵌入视频',\n invalidUrl: 'URL 无效 \\u2014 请输入有效的视频链接。',\n },\n\n emojiDialog: {\n ariaLabel: '插入表情',\n title: '插入表情',\n searchPlaceholder: '搜索表情\\u2026',\n all: '全部',\n cancelBtn: '取消',\n close: '关闭',\n categories: {\n smileys: '笑脸',\n people: '人物',\n animals: '动物',\n food: '食物',\n travel: '旅行',\n objects: '物品',\n symbols: '符号',\n },\n },\n\n iconDialog: {\n ariaLabel: '插入 FA 图标',\n title: '插入 FA 图标',\n searchPlaceholder: '搜索图标\\u2026',\n all: '全部',\n style: '样式',\n size: '大小',\n color: '颜色',\n useColor: ' 使用颜色',\n selectHint: '请选择一个图标',\n insertBtn: '插入 FA 图标',\n cancelBtn: '取消',\n close: '关闭',\n categories: {\n popular: '热门',\n interface: '界面',\n navigation: '导航',\n media: '媒体',\n communication: '通讯',\n files: '文件',\n people: '人物',\n objects: '物品',\n },\n },\n\n findReplace: {\n findTitle: '搜索',\n findReplaceTitle: '查找和替换',\n findPlaceholder: '查找\\u2026',\n searchAriaLabel: '搜索文字',\n caseSensitive: '\\u00a0区分大小写',\n prevBtn: '\\u2190 上一个',\n nextBtn: '下一个 \\u2192',\n replacePlaceholder: '替换为\\u2026',\n replaceAriaLabel: '替换为',\n replaceBtn: '替换',\n replaceAllBtn: '全部替换',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: '键盘快捷键',\n ariaLabel: '键盘快捷键',\n close: '关闭',\n shortcuts: [\n {\n category: '文字格式',\n items: [\n { keys: 'Ctrl + B', action: '粗体' },\n { keys: 'Ctrl + I', action: '斜体' },\n { keys: 'Ctrl + U', action: '下划线' },\n { keys: 'Ctrl + K', action: '插入 / 编辑链接' },\n ],\n },\n {\n category: '历史记录',\n items: [\n { keys: 'Ctrl + Z', action: '撤销' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: '重做' },\n ],\n },\n {\n category: '选择与导航',\n items: [\n { keys: 'Ctrl + A', action: '全选' },\n { keys: 'Tab', action: '增加缩进 / 插入空格' },\n { keys: 'Shift + Tab', action: '减少缩进' },\n ],\n },\n {\n category: '剪贴板',\n items: [\n { keys: 'Ctrl + Shift + V', action: '粘贴为纯文本' },\n ],\n },\n {\n category: '查找和替换',\n items: [\n { keys: 'Ctrl + F', action: '在文档中搜索' },\n { keys: 'Ctrl + H', action: '查找和替换' },\n ],\n },\n {\n category: '编辑器',\n items: [\n { keys: 'Ctrl + Shift + /', action: '显示快捷键对话框' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: '剪切',\n copy: '复制',\n paste: '粘贴',\n bold: '粗体',\n italic: '斜体',\n underline: '下划线',\n textColor: '文字颜色',\n highlightColor: '高亮颜色',\n copyFormat: '复制格式',\n pasteFormat: '粘贴格式',\n removeFormat: '清除格式',\n link: '插入链接',\n image: '插入图片',\n video: '插入视频',\n table: '插入表格',\n back: '返回',\n noHighlight: '无高亮',\n customColor: '自定义颜色',\n customColorLabel: '自定义\\u2026',\n },\n\n statusbar: {\n resizeHandle: '拖动以调整大小',\n words: (n) => `字数: ${n}`,\n wordsLimit: (n, max) => `字数: ${n}/${max}`,\n chars: (n) => `字符数: ${n}`,\n charsLimit: (n, max) => `字符数: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: '链接操作',\n openLink: '打开链接',\n copyUrl: '复制 URL',\n editLink: '编辑链接',\n removeLink: '删除链接',\n },\n image: {\n ariaLabel: '图片操作',\n label: '图片',\n floatLeft: '左浮动',\n noFloat: '不浮动',\n alignCenter: '居中对齐',\n floatRight: '右浮动',\n originalSize: '原始尺寸',\n rotateLeft: '向左旋转',\n rotateRight: '向右旋转',\n cropImage: '裁剪图片',\n addCaption: '添加 / 编辑说明',\n deleteImage: '删除图片',\n },\n code: {\n ariaLabel: '代码块操作',\n label: '代码',\n syntaxLanguage: '语法语言',\n syntaxAriaLabel: '语法语言',\n copyCode: '复制代码',\n toggleWordWrap: '切换自动换行',\n enableWordWrap: '启用自动换行',\n disableWordWrap: '禁用自动换行',\n convertToParagraph: '转换为段落',\n deleteCodeBlock: '删除代码块',\n },\n table: {\n ariaLabel: '表格操作',\n label: '表格',\n selectCells: '选择单元格',\n addRowAbove: '在上方插入行',\n addRowBelow: '在下方插入行',\n deleteRow: '删除行',\n addColumnLeft: '在左侧插入列',\n addColumnRight: '在右侧插入列',\n deleteColumn: '删除列',\n mergeCells: '合并单元格',\n unmergeCells: '拆分单元格',\n columnWidth: '列宽',\n rowHeight: '行高',\n tableBorderWidth: '表格边框宽度',\n deleteTable: '删除表格',\n columnWidthPx: '列宽 (px)',\n rowHeightPx: '行高 (px)',\n tableBorderWidthPx: '表格边框宽度 (px)',\n cancelBtn: '取消',\n applyBtn: '应用',\n },\n video: {\n ariaLabel: '视频操作',\n label: '视频',\n floatLeft: '左浮动',\n noFloat: '不浮动',\n alignCenter: '居中对齐',\n floatRight: '右浮动',\n originalSize: '原始尺寸',\n previewVideo: '预览视频',\n exitPreview: '退出预览',\n deleteVideo: '删除视频',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `格式 \"${type}\" 不支持在浏览器中显示。请转换为 JPEG、PNG 或 WebP。`,\n imageSize: (maxSize) =>\n `图片文件过大。最大允许大小为 ${maxSize} MB。`,\n },\n};\n","/**\n * fr.js - Français (French) locale\n * Seules les clés différentes de en.js sont définies ici.\n * Les clés manquantes sont complétées par en.js via deep-merge dans resolveLocale.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const fr = {\n toolbar: {\n bold: 'Gras (Ctrl+B)',\n italic: 'Italique (Ctrl+I)',\n underline: 'Souligné (Ctrl+U)',\n strikethrough: 'Barré',\n superscript: 'Exposant',\n subscript: 'Indice',\n alignLeft: 'Aligner à gauche',\n alignCenter: 'Centrer',\n alignRight: 'Aligner à droite',\n alignJustify: 'Justifier',\n ul: 'Liste à puces',\n ol: 'Liste numérotée',\n checklist: 'Liste de tâches',\n indent: 'Augmenter le retrait',\n outdent: 'Diminuer le retrait',\n undo: 'Annuler (Ctrl+Z)',\n redo: 'Rétablir (Ctrl+Y)',\n hr: 'Ligne horizontale',\n link: 'Insérer un lien',\n image: 'Insérer une image',\n video: 'Insérer une vidéo',\n emoji: 'Insérer un emoji',\n icon: 'Insérer une icône FA',\n table: 'Insérer un tableau',\n fontSize: 'Taille de police',\n fontSizePlaceholder: 'Taille',\n removeFormat: 'Effacer la mise en forme',\n direction: 'Basculer la direction du texte (LTR / RTL)',\n fontFamily: 'Police',\n paragraphStyle: 'Style de paragraphe',\n paragraphStylePlaceholder: 'Style',\n lineHeight: 'Interligne',\n lineHeightPlaceholder: '\\u2195 Ligne',\n codeview: 'Afficher le code HTML',\n fullscreen: 'Plein écran',\n shortcuts: 'Raccourcis clavier (Ctrl+Shift+/)',\n find: 'Rechercher (Ctrl+F)',\n findReplace: 'Rechercher et remplacer (Ctrl+H)',\n inlineCode: 'Code inline (Ctrl+`)',\n print: 'Imprimer',\n foreColor: 'Couleur du texte',\n backColor: 'Couleur de surbrillance',\n chooseTextColor: 'Choisir la couleur du texte',\n chooseHighlightColor: 'Choisir la couleur de surbrillance',\n customColor: 'Couleur personnalisée',\n insertTableLabel: 'Insérer un tableau',\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Citation',\n pre: 'Code',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Insérer un lien',\n title: 'Insérer un lien',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Texte affiché',\n textPlaceholder: 'Texte du lien',\n openInNewTab: 'Ouvrir dans un nouvel onglet',\n insertBtn: 'Insérer',\n cancelBtn: 'Annuler',\n },\n\n imageDialog: {\n ariaLabel: 'Insérer une image',\n title: 'Insérer une image',\n imageUrl: 'URL de l\\'image',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Texte alternatif',\n altPlaceholder: 'Description de l\\'image',\n alignment: 'Alignement',\n alignNone: 'Aucun',\n alignLeft: 'Gauche',\n alignCenter: 'Centre',\n alignRight: 'Droite',\n uploadLabel: 'Ou téléverser un fichier',\n insertBtn: 'Insérer',\n cancelBtn: 'Annuler',\n },\n\n videoDialog: {\n ariaLabel: 'Insérer une vidéo',\n title: 'Insérer une vidéo',\n videoUrl: 'URL de la vidéo',\n urlPlaceholder: 'YouTube, Vimeo ou URL .mp4 directe',\n widthLabel: 'Largeur (px)',\n widthPlaceholder: '560',\n insertBtn: 'Insérer',\n cancelBtn: 'Annuler',\n detected: (type) => `Détecté\\u00a0: ${type}`,\n unknownFormat: 'Format inconnu \\u2014 tentative d\\'intégration directe',\n invalidUrl: 'URL invalide \\u2014 veuillez saisir un lien vidéo valide.',\n },\n\n emojiDialog: {\n ariaLabel: 'Insérer un emoji',\n title: 'Insérer un emoji',\n searchPlaceholder: 'Rechercher des emojis\\u2026',\n all: 'Tout',\n cancelBtn: 'Annuler',\n close: 'Fermer',\n categories: {\n smileys: 'Smileys',\n people: 'Personnes',\n animals: 'Animaux',\n food: 'Nourriture',\n travel: 'Voyage',\n objects: 'Objets',\n symbols: 'Symboles',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Insérer une icône FA',\n title: 'Insérer une icône FA',\n searchPlaceholder: 'Rechercher des icônes\\u2026',\n all: 'Tout',\n style: 'Style',\n size: 'Taille',\n color: 'Couleur',\n useColor: ' Utiliser la couleur',\n selectHint: 'Sélectionner une icône',\n insertBtn: 'Insérer une icône FA',\n cancelBtn: 'Annuler',\n close: 'Fermer',\n categories: {\n popular: 'Populaire',\n interface: 'Interface',\n navigation: 'Navigation',\n media: 'Média',\n communication: 'Communication',\n files: 'Fichiers',\n people: 'Personnes',\n objects: 'Objets',\n },\n },\n\n findReplace: {\n findTitle: 'Rechercher',\n findReplaceTitle: 'Rechercher et remplacer',\n findPlaceholder: 'Rechercher\\u2026',\n searchAriaLabel: 'Texte à rechercher',\n caseSensitive: '\\u00a0Respecter la casse',\n prevBtn: '\\u2190 Préc.',\n nextBtn: 'Suiv. \\u2192',\n replacePlaceholder: 'Remplacer par\\u2026',\n replaceAriaLabel: 'Remplacer par',\n replaceBtn: 'Remplacer',\n replaceAllBtn: 'Tout remplacer',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'Raccourcis clavier',\n ariaLabel: 'Raccourcis clavier',\n close: 'Fermer',\n shortcuts: [\n {\n category: 'Mise en forme du texte',\n items: [\n { keys: 'Ctrl + B', action: 'Gras' },\n { keys: 'Ctrl + I', action: 'Italique' },\n { keys: 'Ctrl + U', action: 'Souligné' },\n { keys: 'Ctrl + K', action: 'Insérer / modifier un lien' },\n ],\n },\n {\n category: 'Historique',\n items: [\n { keys: 'Ctrl + Z', action: 'Annuler' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Rétablir' },\n ],\n },\n {\n category: 'Sélection et navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Tout sélectionner' },\n { keys: 'Tab', action: 'Augmenter le retrait / insérer des espaces' },\n { keys: 'Shift + Tab', action: 'Diminuer le retrait' },\n ],\n },\n {\n category: 'Presse-papiers',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Coller en texte brut' },\n ],\n },\n {\n category: 'Rechercher et remplacer',\n items: [\n { keys: 'Ctrl + F', action: 'Rechercher dans le document' },\n { keys: 'Ctrl + H', action: 'Rechercher et remplacer' },\n ],\n },\n {\n category: 'Éditeur',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Afficher les raccourcis clavier' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Couper',\n copy: 'Copier',\n paste: 'Coller',\n bold: 'Gras',\n italic: 'Italique',\n underline: 'Souligné',\n textColor: 'Couleur du texte',\n highlightColor: 'Couleur de surbrillance',\n copyFormat: 'Copier la mise en forme',\n pasteFormat: 'Coller la mise en forme',\n removeFormat: 'Effacer la mise en forme',\n link: 'Insérer un lien',\n image: 'Insérer une image',\n video: 'Insérer une vidéo',\n table: 'Insérer un tableau',\n back: 'Retour',\n noHighlight: 'Sans surbrillance',\n customColor: 'Couleur personnalisée',\n customColorLabel: 'Personnaliser\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'Faire glisser pour redimensionner',\n words: (n) => `Mots\\u00a0: ${n}`,\n wordsLimit: (n, max) => `Mots\\u00a0: ${n}/${max}`,\n chars: (n) => `Caractères\\u00a0: ${n}`,\n charsLimit: (n, max) => `Caractères\\u00a0: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Actions du lien',\n openLink: 'Ouvrir le lien',\n copyUrl: 'Copier l\\'URL',\n editLink: 'Modifier le lien',\n removeLink: 'Supprimer le lien',\n },\n image: {\n ariaLabel: 'Actions de l\\'image',\n label: 'Image',\n floatLeft: 'Flottant à gauche',\n noFloat: 'Sans flottant',\n alignCenter: 'Centré',\n floatRight: 'Flottant à droite',\n originalSize: 'Taille originale',\n rotateLeft: 'Rotation à gauche',\n rotateRight: 'Rotation à droite',\n cropImage: 'Recadrer l\\'image',\n addCaption: 'Ajouter / modifier la légende',\n deleteImage: 'Supprimer l\\'image',\n },\n code: {\n ariaLabel: 'Actions du bloc de code',\n label: 'Code',\n syntaxLanguage: 'Langage de syntaxe',\n syntaxAriaLabel: 'Langage de syntaxe',\n copyCode: 'Copier le code',\n toggleWordWrap: 'Activer/désactiver le retour à la ligne',\n enableWordWrap: 'Activer le retour à la ligne',\n disableWordWrap: 'Désactiver le retour à la ligne',\n convertToParagraph: 'Convertir en paragraphe',\n deleteCodeBlock: 'Supprimer le bloc de code',\n },\n table: {\n ariaLabel: 'Actions du tableau',\n label: 'Tableau',\n selectCells: 'Sélectionner des cellules',\n addRowAbove: 'Ajouter une ligne au-dessus',\n addRowBelow: 'Ajouter une ligne en-dessous',\n deleteRow: 'Supprimer la ligne',\n addColumnLeft: 'Ajouter une colonne à gauche',\n addColumnRight: 'Ajouter une colonne à droite',\n deleteColumn: 'Supprimer la colonne',\n mergeCells: 'Fusionner les cellules',\n unmergeCells: 'Scinder les cellules',\n columnWidth: 'Largeur de colonne',\n rowHeight: 'Hauteur de ligne',\n tableBorderWidth: 'Épaisseur des bordures',\n deleteTable: 'Supprimer le tableau',\n columnWidthPx: 'Largeur de colonne (px)',\n rowHeightPx: 'Hauteur de ligne (px)',\n tableBorderWidthPx: 'Épaisseur des bordures (px)',\n cancelBtn: 'Annuler',\n applyBtn: 'Appliquer',\n },\n video: {\n ariaLabel: 'Actions de la vidéo',\n label: 'Vidéo',\n floatLeft: 'Flottant à gauche',\n noFloat: 'Sans flottant',\n alignCenter: 'Centré',\n floatRight: 'Flottant à droite',\n originalSize: 'Taille originale',\n previewVideo: 'Aperçu',\n exitPreview: 'Quitter l\\'aperçu',\n deleteVideo: 'Supprimer la vidéo',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `Le format \"${type}\" n'est pas pris en charge par le navigateur. Veuillez le convertir en JPEG, PNG ou WebP.`,\n imageSize: (maxSize) =>\n `Le fichier image est trop volumineux. La taille maximale autorisée est de ${maxSize}\\u00a0Mo.`,\n },\n};\n","/**\n * de.js - German locale\n * Deep-merged over en.js; only keys that differ from English are listed.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const de = {\n toolbar: {\n bold: 'Fett (Ctrl+B)',\n italic: 'Kursiv (Ctrl+I)',\n underline: 'Unterstrichen (Ctrl+U)',\n strikethrough: 'Durchgestrichen',\n superscript: 'Hochgestellt',\n subscript: 'Tiefgestellt',\n alignLeft: 'Linksbündig',\n alignCenter: 'Zentriert',\n alignRight: 'Rechtsbündig',\n alignJustify: 'Blocksatz',\n ul: 'Ungeordnete Liste',\n ol: 'Geordnete Liste',\n checklist: 'Checkliste',\n indent: 'Einzug vergrößern',\n outdent: 'Einzug verkleinern',\n undo: 'Rückgängig (Ctrl+Z)',\n redo: 'Wiederholen (Ctrl+Y)',\n hr: 'Horizontale Linie',\n link: 'Link einfügen',\n image: 'Bild einfügen',\n video: 'Video einfügen',\n emoji: 'Emoji einfügen',\n icon: 'FA-Symbol einfügen',\n table: 'Tabelle einfügen',\n fontSize: 'Schriftgröße',\n fontSizePlaceholder: 'Größe',\n removeFormat: 'Formatierung entfernen',\n direction: 'Textrichtung umschalten (LTR / RTL)',\n fontFamily: 'Schriftart',\n paragraphStyle: 'Absatzstil',\n paragraphStylePlaceholder: 'Stil',\n lineHeight: 'Zeilenhöhe',\n lineHeightPlaceholder: '↕ Zeile',\n codeview: 'HTML-Code-Ansicht',\n fullscreen: 'Vollbild',\n shortcuts: 'Tastenkürzel (Ctrl+Shift+/)',\n find: 'Suchen (Ctrl+F)',\n findReplace: 'Suchen & Ersetzen (Ctrl+H)',\n inlineCode: 'Inline-Code (Ctrl+`)',\n print: 'Drucken',\n foreColor: 'Textfarbe',\n backColor: 'Hervorhebungsfarbe',\n chooseTextColor: 'Textfarbe auswählen',\n chooseHighlightColor: 'Hervorhebungsfarbe auswählen',\n customColor: 'Benutzerdefinierte Farbe',\n insertTableLabel: 'Tabelle einfügen',\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Zitat',\n pre: 'Code',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Link einfügen',\n title: 'Link einfügen',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Anzeigetext',\n textPlaceholder: 'Linktext',\n openInNewTab: 'In neuem Tab öffnen',\n insertBtn: 'Einfügen',\n cancelBtn: 'Abbrechen',\n },\n\n imageDialog: {\n ariaLabel: 'Bild einfügen',\n title: 'Bild einfügen',\n imageUrl: 'Bild-URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Alt-Text',\n altPlaceholder: 'Bild beschreiben',\n alignment: 'Ausrichtung',\n alignNone: 'Keine',\n alignLeft: 'Links',\n alignCenter: 'Mitte',\n alignRight: 'Rechts',\n uploadLabel: 'Oder Datei hochladen',\n insertBtn: 'Einfügen',\n cancelBtn: 'Abbrechen',\n },\n\n videoDialog: {\n ariaLabel: 'Video einfügen',\n title: 'Video einfügen',\n videoUrl: 'Video-URL',\n urlPlaceholder: 'YouTube, Vimeo oder direkte .mp4-URL',\n widthLabel: 'Breite (px)',\n widthPlaceholder: '560',\n insertBtn: 'Einfügen',\n cancelBtn: 'Abbrechen',\n detected: (type) => `Erkannt: ${type}`,\n unknownFormat: 'Unbekanntes Format — direktes Video-Einbetten wird versucht',\n invalidUrl: 'Ungültige URL — bitte geben Sie einen gültigen Videolink ein.',\n },\n\n emojiDialog: {\n ariaLabel: 'Emoji einfügen',\n title: 'Emoji einfügen',\n searchPlaceholder: 'Emojis suchen…',\n all: 'Alle',\n cancelBtn: 'Abbrechen',\n close: 'Schließen',\n categories: {\n smileys: 'Smileys',\n people: 'Menschen',\n animals: 'Tiere',\n food: 'Essen',\n travel: 'Reisen',\n objects: 'Objekte',\n symbols: 'Symbole',\n },\n },\n\n iconDialog: {\n ariaLabel: 'FA-Symbol einfügen',\n title: 'FA-Symbol einfügen',\n searchPlaceholder: 'Symbole suchen…',\n all: 'Alle',\n style: 'Stil',\n size: 'Größe',\n color: 'Farbe',\n useColor: ' Farbe verwenden',\n selectHint: 'Symbol auswählen',\n insertBtn: 'FA-Symbol einfügen',\n cancelBtn: 'Abbrechen',\n close: 'Schließen',\n categories: {\n popular: 'Beliebt',\n interface: 'Benutzeroberfläche',\n navigation: 'Navigation',\n media: 'Medien',\n communication: 'Kommunikation',\n files: 'Dateien',\n people: 'Menschen',\n objects: 'Objekte',\n },\n },\n\n findReplace: {\n findTitle: 'Suchen',\n findReplaceTitle: 'Suchen & Ersetzen',\n findPlaceholder: 'Suchen…',\n searchAriaLabel: 'Suchtext',\n caseSensitive: '\\u00a0Groß-/Kleinschreibung',\n prevBtn: '← Zurück',\n nextBtn: 'Weiter →',\n replacePlaceholder: 'Ersetzen durch…',\n replaceAriaLabel: 'Ersetzen durch',\n replaceBtn: 'Ersetzen',\n replaceAllBtn: 'Alle ersetzen',\n close: '×',\n },\n\n shortcutsDialog: {\n title: 'Tastenkürzel',\n ariaLabel: 'Tastenkürzel',\n close: 'Schließen',\n shortcuts: [\n {\n category: 'Textformatierung',\n items: [\n { keys: 'Ctrl + B', action: 'Fett' },\n { keys: 'Ctrl + I', action: 'Kursiv' },\n { keys: 'Ctrl + U', action: 'Unterstrichen' },\n { keys: 'Ctrl + K', action: 'Link einfügen / bearbeiten' },\n ],\n },\n {\n category: 'Verlauf',\n items: [\n { keys: 'Ctrl + Z', action: 'Rückgängig' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Wiederholen' },\n ],\n },\n {\n category: 'Auswahl & Navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Alles auswählen' },\n { keys: 'Tab', action: 'Listenebene erhöhen / Leerzeichen einfügen' },\n { keys: 'Shift + Tab', action: 'Listenebene verringern' },\n ],\n },\n {\n category: 'Zwischenablage',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Als einfachen Text einfügen' },\n ],\n },\n {\n category: 'Suchen & Ersetzen',\n items: [\n { keys: 'Ctrl + F', action: 'Im Dokument suchen' },\n { keys: 'Ctrl + H', action: 'Suchen & Ersetzen' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Diesen Tastenkürzel-Dialog anzeigen' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Ausschneiden',\n copy: 'Kopieren',\n paste: 'Einfügen',\n bold: 'Fett',\n italic: 'Kursiv',\n underline: 'Unterstrichen',\n textColor: 'Textfarbe',\n highlightColor: 'Hervorhebungsfarbe',\n copyFormat: 'Format kopieren',\n pasteFormat: 'Format einfügen',\n removeFormat: 'Formatierung entfernen',\n link: 'Link einfügen',\n image: 'Bild einfügen',\n video: 'Video einfügen',\n table: 'Tabelle einfügen',\n back: 'Zurück',\n noHighlight: 'Keine Hervorhebung',\n customColor: 'Benutzerdefinierte Farbe',\n customColorLabel: 'Benutzerdefiniert…',\n },\n\n statusbar: {\n resizeHandle: 'Editor-Größe ändern',\n words: (n) => `Wörter: ${n}`,\n wordsLimit: (n, max) => `Wörter: ${n}/${max}`,\n chars: (n) => `Zeichen: ${n}`,\n charsLimit: (n, max) => `Zeichen: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Link-Aktionen',\n openLink: 'Link öffnen',\n copyUrl: 'URL kopieren',\n editLink: 'Link bearbeiten',\n removeLink: 'Link entfernen',\n },\n image: {\n ariaLabel: 'Bild-Aktionen',\n label: 'Bild',\n floatLeft: 'Links umfließen',\n noFloat: 'Kein Umfluss',\n alignCenter: 'Zentriert',\n floatRight: 'Rechts umfließen',\n originalSize: 'Originalgröße',\n rotateLeft: 'Links drehen',\n rotateRight: 'Rechts drehen',\n cropImage: 'Bild zuschneiden',\n addCaption: 'Beschriftung hinzufügen / bearbeiten',\n deleteImage: 'Bild löschen',\n },\n code: {\n ariaLabel: 'Codeblock-Aktionen',\n label: 'Code',\n syntaxLanguage: 'Syntaxsprache',\n syntaxAriaLabel: 'Syntaxsprache',\n copyCode: 'Code kopieren',\n toggleWordWrap: 'Zeilenumbruch umschalten',\n enableWordWrap: 'Zeilenumbruch aktivieren',\n disableWordWrap: 'Zeilenumbruch deaktivieren',\n convertToParagraph: 'In Absatz umwandeln',\n deleteCodeBlock: 'Codeblock löschen',\n },\n table: {\n ariaLabel: 'Tabellen-Aktionen',\n label: 'Tabelle',\n selectCells: 'Zellen auswählen',\n addRowAbove: 'Zeile oben hinzufügen',\n addRowBelow: 'Zeile unten hinzufügen',\n deleteRow: 'Zeile löschen',\n addColumnLeft: 'Spalte links hinzufügen',\n addColumnRight: 'Spalte rechts hinzufügen',\n deleteColumn: 'Spalte löschen',\n mergeCells: 'Zellen zusammenführen',\n unmergeCells: 'Zellen trennen',\n columnWidth: 'Spaltenbreite',\n rowHeight: 'Zeilenhöhe',\n tableBorderWidth: 'Tabellenrahmenbreite',\n deleteTable: 'Tabelle löschen',\n columnWidthPx: 'Spaltenbreite (px)',\n rowHeightPx: 'Zeilenhöhe (px)',\n tableBorderWidthPx: 'Tabellenrahmenbreite (px)',\n cancelBtn: 'Abbrechen',\n applyBtn: 'Anwenden',\n },\n video: {\n ariaLabel: 'Video-Aktionen',\n label: 'Video',\n floatLeft: 'Links umfließen',\n noFloat: 'Kein Umfluss',\n alignCenter: 'Zentriert',\n floatRight: 'Rechts umfließen',\n originalSize: 'Originalgröße',\n previewVideo: 'Video-Vorschau',\n exitPreview: 'Vorschau beenden',\n deleteVideo: 'Video löschen',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `Das Format „${type}\" wird in Webbrowsern nicht unterstützt. Bitte konvertieren Sie es zuerst in JPEG, PNG oder WebP.`,\n imageSize: (maxSize) =>\n `Die Bilddatei ist zu groß. Die maximal zulässige Größe beträgt ${maxSize} MB.`,\n },\n};\n","/**\n * es.js - Spanish locale\n * Deep-merged over en.js; only keys that differ from English are listed.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const es = {\n toolbar: {\n bold: 'Negrita (Ctrl+B)',\n italic: 'Cursiva (Ctrl+I)',\n underline: 'Subrayado (Ctrl+U)',\n strikethrough: 'Tachado',\n superscript: 'Superíndice',\n subscript: 'Subíndice',\n alignLeft: 'Alinear a la izquierda',\n alignCenter: 'Centrar',\n alignRight: 'Alinear a la derecha',\n alignJustify: 'Justificar',\n ul: 'Lista sin orden',\n ol: 'Lista ordenada',\n checklist: 'Lista de verificación',\n indent: 'Aumentar sangría',\n outdent: 'Reducir sangría',\n undo: 'Deshacer (Ctrl+Z)',\n redo: 'Rehacer (Ctrl+Y)',\n hr: 'Línea horizontal',\n link: 'Insertar enlace',\n image: 'Insertar imagen',\n video: 'Insertar vídeo',\n emoji: 'Insertar emoji',\n icon: 'Insertar icono FA',\n table: 'Insertar tabla',\n fontSize: 'Tamaño de fuente',\n fontSizePlaceholder: 'Tamaño',\n removeFormat: 'Eliminar formato',\n direction: 'Cambiar dirección del texto (LTR / RTL)',\n fontFamily: 'Fuente',\n paragraphStyle: 'Estilo de párrafo',\n paragraphStylePlaceholder: 'Estilo',\n lineHeight: 'Interlineado',\n lineHeightPlaceholder: '↕ Línea',\n codeview: 'Vista de código HTML',\n fullscreen: 'Pantalla completa',\n shortcuts: 'Atajos de teclado (Ctrl+Shift+/)',\n find: 'Buscar (Ctrl+F)',\n findReplace: 'Buscar y reemplazar (Ctrl+H)',\n inlineCode: 'Código en línea (Ctrl+`)',\n print: 'Imprimir',\n foreColor: 'Color del texto',\n backColor: 'Color de resaltado',\n chooseTextColor: 'Elegir color del texto',\n chooseHighlightColor: 'Elegir color de resaltado',\n customColor: 'Color personalizado',\n insertTableLabel: 'Insertar tabla',\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Cita',\n pre: 'Código',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Insertar enlace',\n title: 'Insertar enlace',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Texto a mostrar',\n textPlaceholder: 'Texto del enlace',\n openInNewTab: 'Abrir en nueva pestaña',\n insertBtn: 'Insertar',\n cancelBtn: 'Cancelar',\n },\n\n imageDialog: {\n ariaLabel: 'Insertar imagen',\n title: 'Insertar imagen',\n imageUrl: 'URL de imagen',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Texto alternativo',\n altPlaceholder: 'Describir la imagen',\n alignment: 'Alineación',\n alignNone: 'Ninguna',\n alignLeft: 'Izquierda',\n alignCenter: 'Centro',\n alignRight: 'Derecha',\n uploadLabel: 'O subir un archivo',\n insertBtn: 'Insertar',\n cancelBtn: 'Cancelar',\n },\n\n videoDialog: {\n ariaLabel: 'Insertar vídeo',\n title: 'Insertar vídeo',\n videoUrl: 'URL del vídeo',\n urlPlaceholder: 'YouTube, Vimeo o URL directa .mp4',\n widthLabel: 'Ancho (px)',\n widthPlaceholder: '560',\n insertBtn: 'Insertar',\n cancelBtn: 'Cancelar',\n detected: (type) => `Detectado: ${type}`,\n unknownFormat: 'Formato desconocido — se intentará incrustar el vídeo directamente',\n invalidUrl: 'URL no válida — introduzca un enlace de vídeo válido.',\n },\n\n emojiDialog: {\n ariaLabel: 'Insertar emoji',\n title: 'Insertar emoji',\n searchPlaceholder: 'Buscar emojis…',\n all: 'Todos',\n cancelBtn: 'Cancelar',\n close: 'Cerrar',\n categories: {\n smileys: 'Caritas',\n people: 'Personas',\n animals: 'Animales',\n food: 'Comida',\n travel: 'Viajes',\n objects: 'Objetos',\n symbols: 'Símbolos',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Insertar icono FA',\n title: 'Insertar icono FA',\n searchPlaceholder: 'Buscar iconos…',\n all: 'Todos',\n style: 'Estilo',\n size: 'Tamaño',\n color: 'Color',\n useColor: ' Usar color',\n selectHint: 'Seleccionar un icono',\n insertBtn: 'Insertar icono FA',\n cancelBtn: 'Cancelar',\n close: 'Cerrar',\n categories: {\n popular: 'Popular',\n interface: 'Interfaz',\n navigation: 'Navegación',\n media: 'Medios',\n communication: 'Comunicación',\n files: 'Archivos',\n people: 'Personas',\n objects: 'Objetos',\n },\n },\n\n findReplace: {\n findTitle: 'Buscar',\n findReplaceTitle: 'Buscar y reemplazar',\n findPlaceholder: 'Buscar…',\n searchAriaLabel: 'Texto de búsqueda',\n caseSensitive: '\\u00a0Distinguir mayúsculas',\n prevBtn: '← Anterior',\n nextBtn: 'Siguiente →',\n replacePlaceholder: 'Reemplazar con…',\n replaceAriaLabel: 'Reemplazar con',\n replaceBtn: 'Reemplazar',\n replaceAllBtn: 'Reemplazar todo',\n close: '×',\n },\n\n shortcutsDialog: {\n title: 'Atajos de teclado',\n ariaLabel: 'Atajos de teclado',\n close: 'Cerrar',\n shortcuts: [\n {\n category: 'Formato de texto',\n items: [\n { keys: 'Ctrl + B', action: 'Negrita' },\n { keys: 'Ctrl + I', action: 'Cursiva' },\n { keys: 'Ctrl + U', action: 'Subrayado' },\n { keys: 'Ctrl + K', action: 'Insertar / editar enlace' },\n ],\n },\n {\n category: 'Historial',\n items: [\n { keys: 'Ctrl + Z', action: 'Deshacer' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Rehacer' },\n ],\n },\n {\n category: 'Selección y navegación',\n items: [\n { keys: 'Ctrl + A', action: 'Seleccionar todo' },\n { keys: 'Tab', action: 'Aumentar sangría / insertar espacios' },\n { keys: 'Shift + Tab', action: 'Reducir sangría' },\n ],\n },\n {\n category: 'Portapapeles',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Pegar como texto plano' },\n ],\n },\n {\n category: 'Buscar y reemplazar',\n items: [\n { keys: 'Ctrl + F', action: 'Buscar en el documento' },\n { keys: 'Ctrl + H', action: 'Buscar y reemplazar' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Mostrar este diálogo de atajos' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Cortar',\n copy: 'Copiar',\n paste: 'Pegar',\n bold: 'Negrita',\n italic: 'Cursiva',\n underline: 'Subrayado',\n textColor: 'Color del texto',\n highlightColor: 'Color de resaltado',\n copyFormat: 'Copiar formato',\n pasteFormat: 'Pegar formato',\n removeFormat: 'Eliminar formato',\n link: 'Insertar enlace',\n image: 'Insertar imagen',\n video: 'Insertar vídeo',\n table: 'Insertar tabla',\n back: 'Atrás',\n noHighlight: 'Sin resaltado',\n customColor: 'Color personalizado',\n customColorLabel: 'Personalizado…',\n },\n\n statusbar: {\n resizeHandle: 'Redimensionar editor',\n words: (n) => `Palabras: ${n}`,\n wordsLimit: (n, max) => `Palabras: ${n}/${max}`,\n chars: (n) => `Caracteres: ${n}`,\n charsLimit: (n, max) => `Caracteres: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Acciones de enlace',\n openLink: 'Abrir enlace',\n copyUrl: 'Copiar URL',\n editLink: 'Editar enlace',\n removeLink: 'Eliminar enlace',\n },\n image: {\n ariaLabel: 'Acciones de imagen',\n label: 'Imagen',\n floatLeft: 'Flotar a la izquierda',\n noFloat: 'Sin flotado',\n alignCenter: 'Centrar',\n floatRight: 'Flotar a la derecha',\n originalSize: 'Tamaño original',\n rotateLeft: 'Rotar a la izquierda',\n rotateRight: 'Rotar a la derecha',\n cropImage: 'Recortar imagen',\n addCaption: 'Añadir / editar pie de foto',\n deleteImage: 'Eliminar imagen',\n },\n code: {\n ariaLabel: 'Acciones de bloque de código',\n label: 'Código',\n syntaxLanguage: 'Lenguaje de sintaxis',\n syntaxAriaLabel: 'Lenguaje de sintaxis',\n copyCode: 'Copiar código',\n toggleWordWrap: 'Alternar ajuste de línea',\n enableWordWrap: 'Activar ajuste de línea',\n disableWordWrap: 'Desactivar ajuste de línea',\n convertToParagraph: 'Convertir en párrafo',\n deleteCodeBlock: 'Eliminar bloque de código',\n },\n table: {\n ariaLabel: 'Acciones de tabla',\n label: 'Tabla',\n selectCells: 'Seleccionar celdas',\n addRowAbove: 'Añadir fila encima',\n addRowBelow: 'Añadir fila debajo',\n deleteRow: 'Eliminar fila',\n addColumnLeft: 'Añadir columna a la izquierda',\n addColumnRight: 'Añadir columna a la derecha',\n deleteColumn: 'Eliminar columna',\n mergeCells: 'Combinar celdas',\n unmergeCells: 'Separar celdas',\n columnWidth: 'Ancho de columna',\n rowHeight: 'Alto de fila',\n tableBorderWidth: 'Grosor del borde de la tabla',\n deleteTable: 'Eliminar tabla',\n columnWidthPx: 'Ancho de columna (px)',\n rowHeightPx: 'Alto de fila (px)',\n tableBorderWidthPx: 'Grosor del borde (px)',\n cancelBtn: 'Cancelar',\n applyBtn: 'Aplicar',\n },\n video: {\n ariaLabel: 'Acciones de vídeo',\n label: 'Vídeo',\n floatLeft: 'Flotar a la izquierda',\n noFloat: 'Sin flotado',\n alignCenter: 'Centrar',\n floatRight: 'Flotar a la derecha',\n originalSize: 'Tamaño original',\n previewVideo: 'Vista previa de vídeo',\n exitPreview: 'Salir de la vista previa',\n deleteVideo: 'Eliminar vídeo',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `El formato \"${type}\" no es compatible con los navegadores web. Por favor, conviértalo primero a JPEG, PNG o WebP.`,\n imageSize: (maxSize) =>\n `El archivo de imagen es demasiado grande. El tamaño máximo permitido es ${maxSize} MB.`,\n },\n};\n","/**\n * ko.js - Korean locale\n * Deep-merged over en.js; only keys that differ from English are listed.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const ko = {\n toolbar: {\n bold: '굵게 (Ctrl+B)',\n italic: '기울임꼴 (Ctrl+I)',\n underline: '밑줄 (Ctrl+U)',\n strikethrough: '취소선',\n superscript: '위 첨자',\n subscript: '아래 첨자',\n alignLeft: '왼쪽 정렬',\n alignCenter: '가운데 정렬',\n alignRight: '오른쪽 정렬',\n alignJustify: '양쪽 정렬',\n ul: '순서 없는 목록',\n ol: '순서 있는 목록',\n checklist: '체크리스트',\n indent: '들여쓰기',\n outdent: '내어쓰기',\n undo: '실행 취소 (Ctrl+Z)',\n redo: '다시 실행 (Ctrl+Y)',\n hr: '수평선',\n link: '링크 삽입',\n image: '이미지 삽입',\n video: '동영상 삽입',\n emoji: '이모지 삽입',\n icon: 'FA 아이콘 삽입',\n table: '표 삽입',\n fontSize: '글꼴 크기',\n fontSizePlaceholder: '크기',\n removeFormat: '서식 제거',\n direction: '텍스트 방향 전환 (LTR / RTL)',\n fontFamily: '글꼴',\n paragraphStyle: '단락 스타일',\n paragraphStylePlaceholder: '스타일',\n lineHeight: '줄 간격',\n lineHeightPlaceholder: '↕ 줄',\n codeview: 'HTML 코드 보기',\n fullscreen: '전체 화면',\n shortcuts: '키보드 단축키 (Ctrl+Shift+/)',\n find: '찾기 (Ctrl+F)',\n findReplace: '찾기 및 바꾸기 (Ctrl+H)',\n inlineCode: '인라인 코드 (Ctrl+`)',\n print: '인쇄',\n foreColor: '글자 색',\n backColor: '강조 색',\n chooseTextColor: '글자 색 선택',\n chooseHighlightColor: '강조 색 선택',\n customColor: '사용자 지정 색',\n insertTableLabel: '표 삽입',\n paragraphItems: {\n p: '기본',\n blockquote: '인용',\n pre: '코드',\n },\n },\n\n linkDialog: {\n ariaLabel: '링크 삽입',\n title: '링크 삽입',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: '표시 텍스트',\n textPlaceholder: '링크 텍스트',\n openInNewTab: '새 탭에서 열기',\n insertBtn: '삽입',\n cancelBtn: '취소',\n },\n\n imageDialog: {\n ariaLabel: '이미지 삽입',\n title: '이미지 삽입',\n imageUrl: '이미지 URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: '대체 텍스트',\n altPlaceholder: '이미지 설명',\n alignment: '정렬',\n alignNone: '없음',\n alignLeft: '왼쪽',\n alignCenter: '가운데',\n alignRight: '오른쪽',\n uploadLabel: '또는 파일 업로드',\n insertBtn: '삽입',\n cancelBtn: '취소',\n },\n\n videoDialog: {\n ariaLabel: '동영상 삽입',\n title: '동영상 삽입',\n videoUrl: '동영상 URL',\n urlPlaceholder: 'YouTube, Vimeo 또는 직접 .mp4 URL',\n widthLabel: '너비 (px)',\n widthPlaceholder: '560',\n insertBtn: '삽입',\n cancelBtn: '취소',\n detected: (type) => `감지됨: ${type}`,\n unknownFormat: '알 수 없는 형식 — 직접 동영상 임베드를 시도합니다',\n invalidUrl: '유효하지 않은 URL — 올바른 동영상 링크를 입력하세요.',\n },\n\n emojiDialog: {\n ariaLabel: '이모지 삽입',\n title: '이모지 삽입',\n searchPlaceholder: '이모지 검색…',\n all: '전체',\n cancelBtn: '취소',\n close: '닫기',\n categories: {\n smileys: '스마일',\n people: '사람',\n animals: '동물',\n food: '음식',\n travel: '여행',\n objects: '사물',\n symbols: '기호',\n },\n },\n\n iconDialog: {\n ariaLabel: 'FA 아이콘 삽입',\n title: 'FA 아이콘 삽입',\n searchPlaceholder: '아이콘 검색…',\n all: '전체',\n style: '스타일',\n size: '크기',\n color: '색상',\n useColor: ' 색상 사용',\n selectHint: '아이콘을 선택하세요',\n insertBtn: 'FA 아이콘 삽입',\n cancelBtn: '취소',\n close: '닫기',\n categories: {\n popular: '인기',\n interface: '인터페이스',\n navigation: '탐색',\n media: '미디어',\n communication: '커뮤니케이션',\n files: '파일',\n people: '사람',\n objects: '사물',\n },\n },\n\n findReplace: {\n findTitle: '찾기',\n findReplaceTitle: '찾기 및 바꾸기',\n findPlaceholder: '찾기…',\n searchAriaLabel: '검색 텍스트',\n caseSensitive: '\\u00a0대소문자 구분',\n prevBtn: '← 이전',\n nextBtn: '다음 →',\n replacePlaceholder: '바꿀 내용…',\n replaceAriaLabel: '바꿀 내용',\n replaceBtn: '바꾸기',\n replaceAllBtn: '모두 바꾸기',\n close: '×',\n },\n\n shortcutsDialog: {\n title: '키보드 단축키',\n ariaLabel: '키보드 단축키',\n close: '닫기',\n shortcuts: [\n {\n category: '텍스트 서식',\n items: [\n { keys: 'Ctrl + B', action: '굵게' },\n { keys: 'Ctrl + I', action: '기울임꼴' },\n { keys: 'Ctrl + U', action: '밑줄' },\n { keys: 'Ctrl + K', action: '링크 삽입 / 편집' },\n ],\n },\n {\n category: '실행 기록',\n items: [\n { keys: 'Ctrl + Z', action: '실행 취소' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: '다시 실행' },\n ],\n },\n {\n category: '선택 및 탐색',\n items: [\n { keys: 'Ctrl + A', action: '전체 선택' },\n { keys: 'Tab', action: '목록 들여쓰기 / 공백 삽입' },\n { keys: 'Shift + Tab', action: '목록 내어쓰기' },\n ],\n },\n {\n category: '클립보드',\n items: [\n { keys: 'Ctrl + Shift + V', action: '일반 텍스트로 붙여넣기' },\n ],\n },\n {\n category: '찾기 및 바꾸기',\n items: [\n { keys: 'Ctrl + F', action: '문서에서 찾기' },\n { keys: 'Ctrl + H', action: '찾기 및 바꾸기' },\n ],\n },\n {\n category: '편집기',\n items: [\n { keys: 'Ctrl + Shift + /', action: '이 단축키 대화상자 표시' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: '잘라내기',\n copy: '복사',\n paste: '붙여넣기',\n bold: '굵게',\n italic: '기울임꼴',\n underline: '밑줄',\n textColor: '글자 색',\n highlightColor: '강조 색',\n copyFormat: '서식 복사',\n pasteFormat: '서식 붙여넣기',\n removeFormat: '서식 제거',\n link: '링크 삽입',\n image: '이미지 삽입',\n video: '동영상 삽입',\n table: '표 삽입',\n back: '뒤로',\n noHighlight: '강조 없음',\n customColor: '사용자 지정 색',\n customColorLabel: '사용자 지정…',\n },\n\n statusbar: {\n resizeHandle: '편집기 크기 조정',\n words: (n) => `단어: ${n}`,\n wordsLimit: (n, max) => `단어: ${n}/${max}`,\n chars: (n) => `글자: ${n}`,\n charsLimit: (n, max) => `글자: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: '링크 작업',\n openLink: '링크 열기',\n copyUrl: 'URL 복사',\n editLink: '링크 편집',\n removeLink: '링크 제거',\n },\n image: {\n ariaLabel: '이미지 작업',\n label: '이미지',\n floatLeft: '왼쪽 배치',\n noFloat: '배치 없음',\n alignCenter: '가운데 정렬',\n floatRight: '오른쪽 배치',\n originalSize: '원본 크기',\n rotateLeft: '왼쪽 회전',\n rotateRight: '오른쪽 회전',\n cropImage: '이미지 자르기',\n addCaption: '캡션 추가 / 편집',\n deleteImage: '이미지 삭제',\n },\n code: {\n ariaLabel: '코드 블록 작업',\n label: '코드',\n syntaxLanguage: '구문 언어',\n syntaxAriaLabel: '구문 언어',\n copyCode: '코드 복사',\n toggleWordWrap: '줄 바꿈 전환',\n enableWordWrap: '줄 바꿈 사용',\n disableWordWrap: '줄 바꿈 해제',\n convertToParagraph: '단락으로 변환',\n deleteCodeBlock: '코드 블록 삭제',\n },\n table: {\n ariaLabel: '표 작업',\n label: '표',\n selectCells: '셀 선택',\n addRowAbove: '위에 행 추가',\n addRowBelow: '아래에 행 추가',\n deleteRow: '행 삭제',\n addColumnLeft: '왼쪽에 열 추가',\n addColumnRight: '오른쪽에 열 추가',\n deleteColumn: '열 삭제',\n mergeCells: '셀 병합',\n unmergeCells: '셀 분할',\n columnWidth: '열 너비',\n rowHeight: '행 높이',\n tableBorderWidth: '표 테두리 너비',\n deleteTable: '표 삭제',\n columnWidthPx: '열 너비 (px)',\n rowHeightPx: '행 높이 (px)',\n tableBorderWidthPx: '표 테두리 너비 (px)',\n cancelBtn: '취소',\n applyBtn: '적용',\n },\n video: {\n ariaLabel: '동영상 작업',\n label: '동영상',\n floatLeft: '왼쪽 배치',\n noFloat: '배치 없음',\n alignCenter: '가운데 정렬',\n floatRight: '오른쪽 배치',\n originalSize: '원본 크기',\n previewVideo: '동영상 미리보기',\n exitPreview: '미리보기 종료',\n deleteVideo: '동영상 삭제',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `\"${type}\" 형식은 웹 브라우저에서 지원되지 않습니다. JPEG, PNG 또는 WebP로 변환해 주세요.`,\n imageSize: (maxSize) =>\n `이미지 파일이 너무 큽니다. 최대 허용 크기는 ${maxSize} MB입니다.`,\n },\n};\n","/**\n * i18n/index.js — Locale registry and resolver for autumn-note-ce.\n *\n * Usage:\n * lang: 'en' → built-in English (default)\n * lang: 'vi' → built-in Vietnamese\n * lang: 'ja' → built-in Japanese\n * lang: 'zh' → built-in Simplified Chinese\n * lang: 'fr' → built-in French\n * lang: 'de' → built-in German\n * lang: 'es' → built-in Spanish\n * lang: 'ko' → built-in Korean\n * lang: { ... } → custom locale object, deep-merged over English\n */\n\nimport { mergeDeep } from '../core/func.js';\nimport { en } from './en.js';\nimport { vi } from './vi.js';\nimport { ja } from './ja.js';\nimport { zh } from './zh.js';\nimport { fr } from './fr.js';\nimport { de } from './de.js';\nimport { es } from './es.js';\nimport { ko } from './ko.js';\n\n/**\n * All built-in locales keyed by their language code.\n * @type {Record<string, Partial<AsnLocale>>}\n */\nexport const locales = { en, vi, ja, zh, fr, de, es, ko };\n\n/**\n * Resolve a locale object from a lang option value.\n *\n * @param {string | Partial<AsnLocale> | null | undefined} lang\n * @returns {AsnLocale} A fully-populated locale (always contains every key from en.js).\n */\nexport function resolveLocale(lang) {\n // Default / English shortcut (no merge needed)\n if (!lang || lang === 'en') return en;\n\n if (typeof lang === 'string') {\n const partial = locales[lang];\n // Unknown language code → fall back to English\n if (!partial) return en;\n return mergeDeep(mergeDeep({}, en), partial);\n }\n\n if (typeof lang === 'object') {\n // Custom locale object supplied directly by the user\n return mergeDeep(mergeDeep({}, en), lang);\n }\n\n return en;\n}\n\n/**\n * @typedef {Object} AsnLocale (see types/index.d.ts for the full definition)\n */\n","/**\n * sanitise.js - Shared HTML and URL sanitisation utilities\n *\n * Single source of truth used by Editor, Clipboard, Codeview, and renderer.\n * DOM-parser based — no regex-based stripping of HTML (avoids bypass tricks).\n */\n\n/** Tags that are unconditionally removed from editor content. */\nconst PROHIBITED_TAGS = ['script', 'style', 'iframe', 'object', 'embed', 'form', 'button'];\n\n/** Attributes whose values must be sanitised as URLs. */\nconst URL_ATTRS = ['href', 'src', 'action', 'formaction'];\n\n/** Trusted hosts for iframe embeds when allowIframes is enabled. */\nconst TRUSTED_IFRAME_HOSTS = new Set([\n 'www.youtube.com',\n 'youtube.com',\n 'm.youtube.com',\n 'www.youtube-nocookie.com',\n 'youtube-nocookie.com',\n 'player.vimeo.com',\n]);\n\n/**\n * Sanitises an HTML string by removing dangerous elements and attributes.\n * Uses DOMParser so the sanitisation follows normal browser parsing rules —\n * no regex shortcuts that can be bypassed by encoding tricks.\n *\n * - Strips PROHIBITED_TAGS (script, style, iframe, object, embed, form, button)\n * - Allows input[type=\"checkbox\"] only inside ul.an-checklist li; removes all other <input>\n * - Removes all on* event-handler attributes\n * - Rejects javascript: and vbscript: URLs in URL attributes\n * - Rejects data: URIs everywhere except img[src] (base64 uploads)\n *\n * @param {string} html\n * @returns {string}\n */\nexport function sanitiseHTML(html, { allowIframes = false } = {}) {\n const doc = new DOMParser().parseFromString(`<body>${html || ''}</body>`, 'text/html');\n\n // Remove outright dangerous elements (optionally preserve iframes for video embeds)\n const tags = allowIframes ? PROHIBITED_TAGS.filter((t) => t !== 'iframe') : PROHIBITED_TAGS;\n tags.forEach((tag) => {\n doc.querySelectorAll(tag).forEach((el) => el.remove());\n });\n\n // Strip dangerous attributes from remaining elements\n doc.querySelectorAll('*').forEach((el) => {\n Array.from(el.attributes).forEach((attr) => {\n // Remove all event handlers (onclick, onload, onerror, …)\n if (attr.name.startsWith('on')) {\n el.removeAttribute(attr.name);\n return;\n }\n // Sanitise URL attributes\n if (URL_ATTRS.includes(attr.name)) {\n const val = attr.value.trim();\n // Block javascript: and vbscript: protocols\n if (/^(javascript|vbscript):/i.test(val)) {\n el.removeAttribute(attr.name);\n return;\n }\n // Allow data: URIs only on img[src] (base64 image uploads); block elsewhere\n if (/^data:/i.test(val) && !(attr.name === 'src' && el.tagName === 'IMG')) {\n el.removeAttribute(attr.name);\n }\n }\n\n // Strip iframe HTML-injection vectors and limit iframe src to trusted hosts.\n if (el.tagName === 'IFRAME') {\n if (attr.name === 'srcdoc') {\n el.removeAttribute(attr.name);\n return;\n }\n if (attr.name === 'src') {\n if (!isTrustedIframeSrc(attr.value)) {\n el.removeAttribute(attr.name);\n }\n return;\n }\n }\n });\n });\n\n // Allow only input[type=\"checkbox\"] inside ul.an-checklist li; strip everything else.\n // This preserves checklist state while blocking arbitrary <input> injection.\n doc.querySelectorAll('input').forEach((el) => {\n const inChecklist = el.closest('ul.an-checklist') !== null &&\n el.closest('li') !== null;\n if (!inChecklist || el.getAttribute('type') !== 'checkbox') {\n el.remove();\n } else {\n // Harden: keep only safe attributes on checklist checkboxes\n Array.from(el.attributes).forEach((attr) => {\n if (!['type', 'checked', 'contenteditable'].includes(attr.name)) {\n el.removeAttribute(attr.name);\n }\n });\n }\n });\n\n return doc.body.innerHTML;\n}\n\n/**\n * Returns true if iframe src points to an approved video host.\n * Relative, protocol-relative and invalid URLs are rejected.\n * @param {string} src\n * @returns {boolean}\n */\nfunction isTrustedIframeSrc(src) {\n const trimmed = (src || '').trim();\n if (!trimmed) return false;\n if (trimmed.startsWith('//') || trimmed.startsWith('/')) return false;\n try {\n const url = new URL(trimmed);\n if (url.protocol !== 'https:') return false;\n return TRUSTED_IFRAME_HOSTS.has(url.hostname.toLowerCase());\n } catch {\n return false;\n }\n}\n\n/**\n * Sanitises a URL string, rejecting dangerous protocols.\n *\n * Blocked protocols: javascript:, vbscript:\n * Optionally blocked: data: (safe to allow for img/src base64 embeds)\n *\n * @param {string} url\n * @param {{ allowData?: boolean }} [opts]\n * @returns {string|null} The original URL if safe, null if rejected.\n */\nexport function sanitiseUrl(url, { allowData = false } = {}) {\n const trimmed = (url || '').trim();\n if (/^(javascript|vbscript):/i.test(trimmed)) return null;\n if (!allowData && /^data:/i.test(trimmed)) return null;\n return url;\n}\n","/**\n * renderer.js - Builds the editor DOM structure\n * Inspired by Summernote's renderer.js\n */\n\nimport { createElement } from './core/dom.js';\nimport { sanitiseHTML } from './core/sanitise.js';\n\n/**\n * Renders the editor layout around the original element.\n *\n * Structure:\n * <div class=\"an-container\">\n * <div class=\"an-toolbar\">...</div>\n * <div class=\"an-editable\" contenteditable=\"true\">...</div>\n * <div class=\"an-statusbar\">...</div>\n * </div>\n *\n * @param {HTMLElement} targetEl - the original element to replace/wrap\n * @param {import('./settings.js').AsnOptions} options\n * @returns {{ container: HTMLElement, editable: HTMLElement }}\n */\nexport function renderLayout(targetEl, options) {\n const container = createElement('div', { class: 'an-container' });\n\n // Editable area\n const editable = createElement('div', {\n class: 'an-editable',\n contenteditable: options.readOnly ? 'false' : 'true',\n spellcheck: String(options.spellcheck !== false),\n 'aria-multiline': 'true',\n 'aria-label': 'Rich text editor',\n role: 'textbox',\n });\n\n // Restore auto-saved content when available; fall back to element content\n let initialContent = '';\n if (options.autoSave && options.autoSaveKey) {\n try { initialContent = localStorage.getItem(options.autoSaveKey) || ''; } catch (_) {}\n }\n if (!initialContent) {\n initialContent = targetEl.tagName === 'TEXTAREA'\n ? (targetEl.value || '').trim()\n : (targetEl.innerHTML || '').trim();\n }\n editable.innerHTML = sanitiseHTML(initialContent, { allowIframes: true });\n\n // Apply default font family so the editable renders in the configured font\n const defaultFont = options.defaultFontFamily || (options.fontFamilies && options.fontFamilies[0]);\n if (defaultFont) {\n editable.style.fontFamily = defaultFont;\n }\n\n // Apply default font size so the size dropdown shows the correct value on startup\n if (options.defaultFontSize) {\n editable.style.fontSize = options.defaultFontSize;\n }\n\n // Apply height options.\n // `height` sets the initial visible height (takes priority).\n // `minHeight` is the drag-resize floor — only applied when no explicit `height` is given.\n if (options.height) {\n editable.style.minHeight = `${options.height}px`;\n } else if (options.minHeight) {\n editable.style.minHeight = `${options.minHeight}px`;\n }\n if (options.maxHeight) {\n editable.style.maxHeight = `${options.maxHeight}px`;\n }\n\n container.appendChild(editable);\n\n // Apply dark theme\n if (options.theme === 'dark') {\n container.classList.add('an-theme-dark');\n }\n\n // Read-only mode\n if (options.readOnly) {\n container.classList.add('an-disabled');\n editable.querySelectorAll('ul.an-checklist input[type=\"checkbox\"]').forEach((cb) => {\n cb.setAttribute('disabled', '');\n });\n }\n\n // Text direction\n if (options.direction === 'rtl') {\n editable.setAttribute('dir', 'rtl');\n container.classList.add('an-dir-rtl');\n }\n\n // Toolbar overflow\n if (options.toolbarOverflow === 'scroll') {\n container.classList.add('an-toolbar-overflow-scroll');\n }\n\n // Configure sticky toolbar\n if (options.stickyToolbar) {\n container.classList.add('an-sticky-toolbar');\n if (options.stickyToolbarOffset) {\n container.style.setProperty('--an-sticky-top', `${options.stickyToolbarOffset}px`);\n }\n }\n\n // Custom focus ring colour\n if (options.focusColor) {\n container.style.setProperty('--an-focus-color', options.focusColor);\n }\n\n // Hide the original element; keep it in DOM for form submission\n targetEl.style.display = 'none';\n targetEl.insertAdjacentElement('afterend', container);\n\n return { container, editable };\n}\n","/**\n * History.js - Undo / redo stack for editor content\n * Inspired by Summernote's History module, rewritten without jQuery\n */\n\nexport class History {\n /**\n * @param {HTMLElement} editable - the contenteditable element\n * @param {number} [limit=100] - maximum number of undo/redo states\n */\n constructor(editable, limit = 100) {\n this.editable = editable;\n this._limit = limit;\n /** @type {Array<{html: string, range: {sc: string, so: number, ec: string, eo: number}|null}>} */\n this.stack = [];\n this.stackOffset = -1;\n this._savePoint();\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n _serialize() {\n return this.editable.innerHTML;\n }\n\n /**\n * Serializes the current selection as character offsets from the start of\n * the editable element, so it can be restored after innerHTML replacement.\n * @returns {{ start: number, end: number }|null}\n */\n _serializeSelection() {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const range = sel.getRangeAt(0);\n if (!this.editable.contains(range.startContainer)) return null;\n return {\n start: this._charOffset(range.startContainer, range.startOffset),\n end: this._charOffset(range.endContainer, range.endOffset),\n };\n }\n\n /**\n * Returns the character offset of (node, offset) from the beginning of\n * the editable's text content.\n * @param {Node} node\n * @param {number} offset\n * @returns {number}\n */\n _charOffset(node, offset) {\n let count = 0;\n const walker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);\n let cur;\n while ((cur = walker.nextNode())) {\n if (cur === node) return count + offset;\n count += cur.length;\n }\n return 0;\n }\n\n /**\n * Restores a previously serialized selection inside the editable.\n * @param {{ start: number, end: number }|null} saved\n */\n _restoreSelection(saved) {\n if (!saved) return;\n let startNode = null, startOff = 0;\n let endNode = null, endOff = 0;\n let count = 0;\n const walker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);\n let cur;\n while ((cur = walker.nextNode())) {\n const len = cur.length;\n if (!startNode && count + len >= saved.start) {\n startNode = cur;\n startOff = saved.start - count;\n }\n if (!endNode && count + len >= saved.end) {\n endNode = cur;\n endOff = saved.end - count;\n break;\n }\n count += len;\n }\n if (!startNode) {\n // Offset exceeds content (e.g. undo to a shorter state): place at end\n const lastWalker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);\n let lastNode = null;\n while ((lastNode = lastWalker.nextNode())) { startNode = lastNode; }\n startOff = startNode ? startNode.length : 0;\n endNode = startNode;\n endOff = startOff;\n }\n if (!endNode) { endNode = startNode; endOff = startOff; }\n try {\n const range = document.createRange();\n range.setStart(startNode, startOff);\n range.setEnd(endNode, endOff);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_) { /* detached node — ignore */ }\n }\n\n _savePoint() {\n // Trim future history if we're mid-stack\n if (this.stackOffset < this.stack.length - 1) {\n this.stack = this.stack.slice(0, this.stackOffset + 1);\n }\n const raw = this._serialize();\n const { html, images } = this._tokenizeImages(raw);\n this.stack.push({ html, images, sel: this._serializeSelection() });\n if (this.stack.length > this._limit) {\n this.stack.shift();\n } else {\n this.stackOffset++;\n }\n }\n\n _restore(point) {\n if (!point) return;\n this.editable.innerHTML = this._detokenizeImages(point);\n this._restoreSelection(point.sel);\n }\n\n // ---------------------------------------------------------------------------\n // Base64 tokenisation — keeps snapshot strings small so that the\n // per-keystroke `recordUndo` string comparison stays fast even when the\n // editor contains large embedded images.\n // ---------------------------------------------------------------------------\n\n /**\n * Replaces every `data:…;base64,…` occurrence in `html` with a compact\n * token `__asn_img_0__`, `__asn_img_1__`, … and returns the tokenized\n * string together with a map from token → original data URL.\n * @param {string} html\n * @returns {{ html: string, images: Object<string,string> }}\n */\n _tokenizeImages(html) {\n const images = {};\n let index = 0;\n const tokenized = html.replace(/data:[^;]+;base64,[^\"' >]*/g, (match) => {\n const token = `__asn_img_${index}__`;\n images[token] = match;\n index++;\n return token;\n });\n return { html: tokenized, images };\n }\n\n /**\n * Restores a snapshot by replacing tokens back with their data URLs.\n * @param {{ html: string, images: Object<string,string> }} point\n * @returns {string}\n */\n _detokenizeImages(point) {\n if (!point.images || Object.keys(point.images).length === 0) return point.html;\n return point.html.replace(/__asn_img_\\d+__/g, (token) => point.images[token] || token);\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Records the current editor state as a history checkpoint.\n */\n recordUndo() {\n const current = this._serialize();\n const { html: tokenized } = this._tokenizeImages(current);\n const prev = this.stack[this.stackOffset];\n if (prev && prev.html === tokenized) return; // No change\n this._savePoint();\n }\n\n /**\n * Undo to the previous state.\n */\n undo() {\n if (this.stackOffset <= 0) return;\n this.stackOffset--;\n this._restore(this.stack[this.stackOffset]);\n }\n\n /**\n * Redo to the next state.\n */\n redo() {\n if (this.stackOffset >= this.stack.length - 1) return;\n this.stackOffset++;\n this._restore(this.stack[this.stackOffset]);\n }\n\n /**\n * Resets the history stack (e.g. on editor destroy or full content replace).\n */\n reset() {\n this.stack = [];\n this.stackOffset = -1;\n this._savePoint();\n }\n\n /** @returns {boolean} */\n canUndo() {\n return this.stackOffset > 0;\n }\n\n /** @returns {boolean} */\n canRedo() {\n return this.stackOffset < this.stack.length - 1;\n }\n}\n","/**\n * Table.js - Table creation and manipulation utilities\n * Inspired by Summernote's table handling\n */\n\nimport { createElement } from '../core/dom.js';\nimport { execCommand } from './Style.js';\n\n// ---------------------------------------------------------------------------\n// Table creation\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a table element with the specified dimensions.\n * @param {number} cols\n * @param {number} rows\n * @param {{ headerRow?: boolean }} [opts]\n * @returns {HTMLTableElement}\n */\nexport function createTable(cols, rows, opts = {}) {\n const { headerRow = false } = opts;\n const table = createElement('table', { class: 'an-table' });\n\n if (headerRow && rows > 0) {\n const thead = createElement('thead');\n const tr = createElement('tr');\n for (let c = 0; c < cols; c++) {\n const th = createElement('th', {}, ['\\u00a0']);\n tr.appendChild(th);\n }\n thead.appendChild(tr);\n table.appendChild(thead);\n }\n\n const bodyRows = headerRow ? Math.max(rows - 1, 1) : rows;\n const tbody = createElement('tbody');\n table.appendChild(tbody);\n\n for (let r = 0; r < bodyRows; r++) {\n const tr = createElement('tr');\n for (let c = 0; c < cols; c++) {\n const td = createElement('td', {}, ['\\u00a0']); // \n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n return table;\n}\n\n/**\n * Inserts a table at the current cursor position.\n * @param {number} cols\n * @param {number} rows\n * @param {{ headerRow?: boolean }} [opts]\n */\nexport function insertTable(cols, rows, opts = {}) {\n const table = createTable(cols, rows, opts);\n execCommand('insertHTML', table.outerHTML);\n}\n","/**\n * key.js - Keyboard key code constants\n * Inspired by Summernote's key.js\n */\n\nexport const key = {\n BACKSPACE: 'Backspace',\n TAB: 'Tab',\n ENTER: 'Enter',\n ESCAPE: 'Escape',\n SPACE: ' ',\n PAGE_UP: 'PageUp',\n PAGE_DOWN: 'PageDown',\n END: 'End',\n HOME: 'Home',\n LEFT: 'ArrowLeft',\n UP: 'ArrowUp',\n RIGHT: 'ArrowRight',\n DOWN: 'ArrowDown',\n DELETE: 'Delete',\n // Numbers\n NUM0: '0',\n NUM1: '1',\n NUM2: '2',\n NUM3: '3',\n NUM4: '4',\n NUM5: '5',\n NUM6: '6',\n NUM7: '7',\n NUM8: '8',\n // Letters\n B: 'b',\n E: 'e',\n I: 'i',\n J: 'j',\n K: 'k',\n L: 'l',\n R: 'r',\n S: 's',\n U: 'u',\n V: 'v',\n Y: 'y',\n Z: 'z',\n SLASH: '/',\n PERIOD: '.',\n};\n\n/**\n * Returns true if the event matches the given key\n * @param {KeyboardEvent} event\n * @param {string} keyName - one of key.*\n * @returns {boolean}\n */\nexport function isKey(event, keyName) {\n return event.key === keyName || event.key === keyName.toUpperCase();\n}\n\n/**\n * Returns true if the event is a modifier key press (Ctrl/Cmd + key)\n * @param {KeyboardEvent} event\n * @param {string} keyName\n * @returns {boolean}\n */\nexport function isModifier(event, keyName) {\n return (event.ctrlKey || event.metaKey) && isKey(event, keyName);\n}\n","/**\n * Typing.js - Keyboard typing event handling (Enter, Tab, Backspace behaviour)\n * Inspired by Summernote's Typing module\n */\n\nimport { key, isKey } from '../core/key.js';\nimport { closestPara, isLi } from '../core/dom.js';\nimport { execCommand, outdent } from './Style.js';\nimport { currentRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// Module-level predicates — defined once, not re-created on every keypress.\n// Previously these were arrow functions inside handleKeydown() which fires\n// at ~120+ events/sec during normal typing.\n// ---------------------------------------------------------------------------\nconst _FA_PATTERN = /\\bfa-/;\nconst isFAIcon = (n) => !!(n && n.nodeName === 'I' && _FA_PATTERN.test(n.className || ''));\nconst isZwsAnchor = (n) => !!(n && n.nodeType === Node.TEXT_NODE && (n.textContent === '\\u200B' || n.textContent === ''));\n\n/**\n * Handles special keydown behaviour inside the editor.\n * @param {KeyboardEvent} event\n * @param {HTMLElement} editable\n * @param {object} options - editor options\n * @returns {boolean} true if the event was consumed\n */\nexport function handleKeydown(event, editable, options = {}) {\n const moveCaret = (setFn) => {\n const sel = window.getSelection();\n if (!sel) return false;\n const nr = document.createRange();\n setFn(nr);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n };\n\n // -------------------------------------------------------------------------\n // Backspace key — one-press deletion of a preceding FA icon (<i> element)\n // -------------------------------------------------------------------------\n if (isKey(event, key.BACKSPACE)) {\n const sel = window.getSelection();\n if (sel && sel.rangeCount > 0) {\n const r = sel.getRangeAt(0);\n if (r.collapsed && r.startContainer.nodeType === Node.TEXT_NODE) {\n const textNode = r.startContainer;\n // Case A: cursor at offset 0, preceding sibling is an FA icon\n if (r.startOffset === 0 && isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n textNode.previousSibling.remove();\n return true;\n }\n\n // Case B: cursor at offset 1 of a ZWS-only text node whose preceding\n // sibling is an FA icon. The ZWS is the invisible caret anchor inserted\n // by IconDialog; treat the whole Backspace as \"delete icon + its anchor\".\n if (r.startOffset === 1 && textNode.textContent === '\\u200B' &&\n isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n const parent = textNode.parentNode;\n const icon = textNode.previousSibling;\n const prevNode = icon.previousSibling; // node before the icon (e.g. ZWS of prior icon)\n icon.remove();\n textNode.remove();\n // Explicitly restore the cursor to the node preceding the deleted icon.\n // Without this, the browser collapses the selection to the parent element\n // (not a text node), causing the next Backspace to miss Cases A/B and\n // requiring an extra keypress when two icons are adjacent.\n const nr = document.createRange();\n if (prevNode && prevNode.nodeType === Node.TEXT_NODE) {\n nr.setStart(prevNode, prevNode.textContent.length);\n } else if (prevNode) {\n nr.setStartAfter(prevNode);\n } else if (parent) {\n nr.setStart(parent, 0);\n }\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n }\n }\n return false;\n }\n\n // -------------------------------------------------------------------------\n // ArrowLeft / ArrowRight — one-press navigation across FA icon nodes\n // -------------------------------------------------------------------------\n if (isKey(event, key.LEFT) || isKey(event, key.RIGHT)) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return false;\n\n const r = sel.getRangeAt(0);\n if (!r.collapsed) return false;\n\n const sc = r.startContainer;\n const movingLeft = isKey(event, key.LEFT);\n\n if (sc.nodeType === Node.TEXT_NODE) {\n const textNode = sc;\n\n if (movingLeft &&\n r.startOffset === 1 &&\n textNode.textContent === '\\u200B' &&\n isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(textNode.previousSibling));\n }\n\n if (movingLeft && r.startOffset === 0 && isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(textNode.previousSibling));\n }\n\n if (movingLeft &&\n r.startOffset === 0 &&\n isZwsAnchor(textNode.previousSibling) &&\n isFAIcon(textNode.previousSibling.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(textNode.previousSibling.previousSibling));\n }\n\n if (!movingLeft &&\n r.startOffset === textNode.textContent.length &&\n isFAIcon(textNode.nextSibling)) {\n const icon = textNode.nextSibling;\n const after = icon.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(icon));\n }\n\n if (!movingLeft &&\n r.startOffset === textNode.textContent.length &&\n isZwsAnchor(textNode.nextSibling) &&\n isFAIcon(textNode.nextSibling.nextSibling)) {\n const icon = textNode.nextSibling.nextSibling;\n const after = icon.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(icon));\n }\n }\n\n if (sc.nodeType === Node.ELEMENT_NODE) {\n const el = sc;\n if (movingLeft && r.startOffset > 0) {\n const prev = el.childNodes[r.startOffset - 1];\n if (isFAIcon(prev)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(prev));\n }\n if (isZwsAnchor(prev) && isFAIcon(prev.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(prev.previousSibling));\n }\n }\n if (!movingLeft && r.startOffset < el.childNodes.length) {\n const next = el.childNodes[r.startOffset];\n if (isFAIcon(next)) {\n const after = next.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(next));\n }\n if (isZwsAnchor(next) && isFAIcon(next.nextSibling)) {\n const icon = next.nextSibling;\n const after = icon.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(icon));\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Tab key — indent / outdent list items, or insert soft tab in code blocks\n // -------------------------------------------------------------------------\n if (isKey(event, key.TAB)) {\n const range = currentRange(editable);\n if (!range) return false;\n\n const para = closestPara(range.sc, editable);\n if (para && isLi(para)) {\n event.preventDefault();\n if (event.shiftKey) {\n outdent();\n } else {\n execCommand('indent');\n }\n return true;\n }\n\n // In a pre/code block, insert spaces\n if (para && para.nodeName.toUpperCase() === 'PRE') {\n if (event.shiftKey) return false;\n event.preventDefault();\n execCommand('insertText', ' ');\n return true;\n }\n\n // Default: insert * tabSize\n if (options.tabSize) {\n if (event.shiftKey) return false;\n event.preventDefault();\n execCommand('insertText', ' '.repeat(options.tabSize));\n return true;\n }\n }\n\n // -------------------------------------------------------------------------\n // Shift+Enter — insert <br> instead of opening a new block element\n // -------------------------------------------------------------------------\n if (isKey(event, key.ENTER) && event.shiftKey) {\n event.preventDefault();\n execCommand('insertLineBreak');\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Enter key — keep consistent paragraph insertion\n // -------------------------------------------------------------------------\n if (isKey(event, key.ENTER) && !event.shiftKey) {\n const range = currentRange(editable);\n if (!range) return false;\n\n // Hoist sc/el once so all guards below can reuse them.\n const sc = range.sc;\n const el = sc.nodeType === 3 ? sc.parentElement : sc;\n\n // Guard: if the cursor is inside a <i> FA icon element (zero text children,\n // rendered entirely by CSS ::before), pressing Enter would split the block\n // and leave an orphan <i> in the new paragraph — visually an \"auto-created\n // icon\". Push the cursor to just after the <i> first, then fall through so\n // the browser fires its default Enter at a safe text boundary.\n if (el && el.nodeName === 'I' && /\\bfa-/.test(el.className || '')) {\n const nr = document.createRange();\n nr.setStartAfter(el);\n nr.collapse(true);\n const selI = window.getSelection();\n if (selI) { selI.removeAllRanges(); selI.addRange(nr); }\n return false; // cursor is now outside <i> — let browser default handle Enter\n }\n\n // Video wrapper — Enter should create a new paragraph after the wrapper,\n // not split the wrapper's container and produce an empty video clone.\n const videoWrapper = el && el.closest && el.closest('.an-video-wrapper');\n if (videoWrapper) {\n event.preventDefault();\n const p = document.createElement('p');\n p.innerHTML = '\\u00a0';\n videoWrapper.parentNode.insertBefore(p, videoWrapper.nextSibling);\n const nr = document.createRange();\n nr.setStart(p, 0);\n nr.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n\n // Checklist — Enter creates new item; empty item exits the list\n const checkLi = el && el.closest && el.closest('.an-checklist li');\n if (checkLi) {\n event.preventDefault();\n const ul = checkLi.closest('.an-checklist');\n const sel = window.getSelection();\n let nativeRange = sel.getRangeAt(0);\n\n // Helper: get trimmed text content of a li, excluding the checkbox INPUT.\n // Strip both \\u00a0 (placeholder nbsp) and \\u200B (ZWS cursor anchors).\n const liText = (li) =>\n Array.from(li.childNodes)\n .filter((n) => !(n.nodeType === 1 && n.tagName === 'INPUT'))\n .map((n) => n.textContent).join('').replace(/[\\u00a0\\u200B]/g, ' ').trim();\n\n // 1. Check if the ENTIRE item is empty BEFORE any DOM mutation.\n // (Do NOT check only the \"before-cursor\" part — that check incorrectly\n // exits the list when cursor is at the start of a non-empty item.)\n if (!liText(checkLi)) {\n // Empty item — exit checklist, insert <p> after list\n const p = document.createElement('p');\n p.innerHTML = '\\u00a0';\n ul.parentNode.insertBefore(p, ul.nextSibling);\n checkLi.remove();\n if (ul.children.length === 0) ul.remove();\n const nr = document.createRange();\n nr.setStart(p.firstChild, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n\n // 2. If selection is not collapsed, delete the selected content first —\n // mirrors browser-default Enter behaviour (delete selection, then split).\n if (!nativeRange.collapsed) {\n nativeRange.deleteContents();\n // nativeRange is now collapsed at the deletion point; re-read it\n nativeRange = sel.getRangeAt(0);\n }\n\n // 3. Extract everything from cursor to end of li into afterFrag.\n // Use startContainer/startOffset (cursor position after potential delete),\n // NOT endContainer/endOffset which is wrong for non-collapsed ranges.\n const afterRange = document.createRange();\n afterRange.setStart(nativeRange.startContainer, nativeRange.startOffset);\n afterRange.setEnd(checkLi, checkLi.childNodes.length);\n const afterFrag = afterRange.extractContents();\n\n // 4. Build the new checklist item with the extracted \"after\" content.\n const newLi = document.createElement('li');\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.setAttribute('contenteditable', 'false');\n newLi.appendChild(cb);\n\n // Append extracted \"after\" content (if any) then insert the new item.\n if (afterFrag.textContent.replace(/[\\u00a0\\u200B]/g, '').length > 0) {\n newLi.appendChild(afterFrag);\n }\n\n // Always ensure a text node exists so the cursor has a text-level\n // anchor. Use \\u200B (zero-width space) instead of an empty string:\n // Chrome does not reliably honour a Selection in an empty text node and\n // may normalise it to element-level, placing the caret before the\n // absolutely-positioned checkbox. \\u200B is stripped by getHTML().\n let cursorNode = newLi.childNodes[1]; // first child after checkbox\n if (!cursorNode || cursorNode.nodeType !== Node.TEXT_NODE) {\n cursorNode = document.createTextNode('\\u200B');\n newLi.appendChild(cursorNode);\n }\n checkLi.insertAdjacentElement('afterend', newLi);\n\n const nr = document.createRange();\n nr.setStart(cursorNode, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n\n const para = closestPara(range.sc, editable);\n\n // Pressing Enter at the end of a blockquote should exit it\n if (para && para.nodeName.toUpperCase() === 'BLOCKQUOTE') {\n const native = range.toNativeRange();\n native.setEnd(para, para.childNodes.length);\n if (native.toString() === '' && range.isCollapsed()) {\n event.preventDefault();\n execCommand('formatBlock', '<p>');\n return true;\n }\n }\n }\n\n return false;\n}\n","/**\n * markdown.js - Lightweight Markdown → HTML converter for paste handling.\n *\n * Handles: headings H1–H6, bold/italic/strikethrough/inline-code, fenced code\n * blocks (with language), blockquotes, unordered/ordered lists, horizontal\n * rules, links, images, and plain paragraphs.\n *\n * The HTML output MUST be passed through sanitiseHTML() before insertion.\n */\n\n/**\n * Converts an HTML string to Markdown.\n * Handles: headings, paragraphs, bold/italic/del/code, links, images,\n * unordered/ordered lists, blockquote, pre/code blocks, tables, hr.\n * @param {string} html\n * @returns {string}\n */\nexport function htmlToMarkdown(html) {\n const doc = new DOMParser().parseFromString(`<body>${html || ''}</body>`, 'text/html');\n return _domToMd(doc.body).replace(/\\n{3,}/g, '\\n\\n').trim();\n}\n\nfunction _domToMd(node) {\n if (node.nodeType === 3) {\n return node.textContent.replace(/\\s+/g, ' ');\n }\n if (node.nodeType !== 1) return '';\n\n const tag = node.nodeName.toLowerCase();\n const inner = () => Array.from(node.childNodes).map(_domToMd).join('');\n\n switch (tag) {\n case 'p':\n case 'div': return `\\n\\n${inner()}\\n\\n`;\n case 'br': return ' \\n';\n case 'h1': return `\\n\\n# ${inner()}\\n\\n`;\n case 'h2': return `\\n\\n## ${inner()}\\n\\n`;\n case 'h3': return `\\n\\n### ${inner()}\\n\\n`;\n case 'h4': return `\\n\\n#### ${inner()}\\n\\n`;\n case 'h5': return `\\n\\n##### ${inner()}\\n\\n`;\n case 'h6': return `\\n\\n###### ${inner()}\\n\\n`;\n case 'strong':\n case 'b': return `**${inner()}**`;\n case 'em':\n case 'i': return `*${inner()}*`;\n case 'del':\n case 's':\n case 'strike': return `~~${inner()}~~`;\n case 'sup': return `^${inner()}`;\n case 'sub': return `~${inner()}`;\n case 'code': {\n // Inside <pre> we emit raw text; outside we wrap in backticks\n if (node.closest('pre')) return inner();\n return `\\`${inner()}\\``;\n }\n case 'pre': {\n const codeEl = node.querySelector('code');\n const langMatch = ((codeEl && codeEl.className) || '').match(/language-(\\S+)/);\n const lang = langMatch ? langMatch[1] : '';\n const content = (codeEl || node).textContent || '';\n return `\\n\\n\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n\\n`;\n }\n case 'blockquote': {\n const lines = inner().trim().split('\\n');\n return `\\n\\n${lines.map((l) => `> ${l}`).join('\\n')}\\n\\n`;\n }\n case 'a': {\n const href = node.getAttribute('href') || '';\n return `[${inner()}](${href})`;\n }\n case 'img': {\n const src = node.getAttribute('src') || '';\n const alt = node.getAttribute('alt') || '';\n return ``;\n }\n case 'ul': {\n const items = Array.from(node.querySelectorAll(':scope > li'));\n if (!items.length) return inner();\n return `\\n\\n${items.map((li) => `- ${_domToMd(li).trim()}`).join('\\n')}\\n\\n`;\n }\n case 'ol': {\n const items = Array.from(node.querySelectorAll(':scope > li'));\n if (!items.length) return inner();\n return `\\n\\n${items.map((li, i) => `${i + 1}. ${_domToMd(li).trim()}`).join('\\n')}\\n\\n`;\n }\n case 'li': return inner();\n case 'hr': return '\\n\\n---\\n\\n';\n case 'table': {\n const rows = Array.from(node.querySelectorAll('tr'));\n if (!rows.length) return inner();\n const cellTexts = rows.map((tr) =>\n Array.from(tr.querySelectorAll('th, td')).map((c) => c.textContent.trim().replace(/\\|/g, '\\\\|')),\n );\n const cols = Math.max(...cellTexts.map((r) => r.length));\n const padRow = (row) => { const r = [...row]; while (r.length < cols) r.push(''); return r; };\n let md = '\\n\\n';\n md += `| ${padRow(cellTexts[0]).join(' | ')} |\\n`;\n md += `| ${Array(cols).fill('---').join(' | ')} |\\n`;\n for (let r = 1; r < cellTexts.length; r++) {\n md += `| ${padRow(cellTexts[r]).join(' | ')} |\\n`;\n }\n return md + '\\n';\n }\n default: return inner();\n }\n}\n\n/**\n * Returns true if the text contains recognisable Markdown patterns.\n * @param {string} text\n * @returns {boolean}\n */\nexport function isMarkdown(text) {\n return /^#{1,6} \\S|^\\s*[-*+] \\S|^\\s*\\d+\\. \\S|^> \\S|\\*{2}.+?\\*{2}|^```/m.test(text);\n}\n\n/**\n * Converts a Markdown string to an HTML string.\n * @param {string} text\n * @returns {string}\n */\nexport function markdownToHTML(text) {\n const lines = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n').split('\\n');\n const out = [];\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i];\n\n // ---- Fenced code block ``` lang ... ``` -----------------------------------\n const fenceMatch = line.match(/^```(\\S*)$/);\n if (fenceMatch) {\n const lang = fenceMatch[1];\n const codeLines = [];\n i++;\n while (i < lines.length && !lines[i].startsWith('```')) {\n codeLines.push(_esc(lines[i]));\n i++;\n }\n const langAttr = lang ? ` class=\"language-${_escAttr(lang)}\"` : '';\n out.push(`<pre><code${langAttr}>${codeLines.join('\\n')}</code></pre>`);\n i++; // skip closing ```\n continue;\n }\n\n // ---- Horizontal rule --- / *** / _________________________________________\n if (/^(-{3,}|\\*{3,}|_{3,})\\s*$/.test(line)) {\n out.push('<hr>');\n i++;\n continue;\n }\n\n // ---- ATX Headings # – ###### -------------------------------------------\n const hMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (hMatch) {\n const level = hMatch[1].length;\n out.push(`<h${level}>${_inline(hMatch[2])}</h${level}>`);\n i++;\n continue;\n }\n\n // ---- Blockquote > text --------------------------------------------------\n if (line.startsWith('> ')) {\n const bqLines = [];\n while (i < lines.length && lines[i].startsWith('> ')) {\n bqLines.push(lines[i].slice(2));\n i++;\n }\n out.push(`<blockquote>${bqLines.map(_inline).join('<br>')}</blockquote>`);\n continue;\n }\n\n // ---- Unordered list - / * / + item ------------------------------------\n if (/^[-*+] /.test(line)) {\n const items = [];\n while (i < lines.length && /^[-*+] /.test(lines[i])) {\n items.push(`<li>${_inline(lines[i].slice(2))}</li>`);\n i++;\n }\n out.push(`<ul>${items.join('')}</ul>`);\n continue;\n }\n\n // ---- Ordered list 1. item ----------------------------------------------\n if (/^\\d+\\. /.test(line)) {\n const items = [];\n while (i < lines.length && /^\\d+\\. /.test(lines[i])) {\n items.push(`<li>${_inline(lines[i].replace(/^\\d+\\. /, ''))}</li>`);\n i++;\n }\n out.push(`<ol>${items.join('')}</ol>`);\n continue;\n }\n\n // ---- Blank line ----------------------------------------------------------\n if (line.trim() === '') {\n i++;\n continue;\n }\n\n // ---- GFM Table | col | col | -------------------------------------------\n // A table starts with a pipe-prefixed or pipe-containing line followed by\n // a separator row (| --- | --- |). We detect and collect all rows.\n if (/^\\|.+\\|/.test(line) && i + 1 < lines.length && /^\\|[\\s|:-]+\\|/.test(lines[i + 1])) {\n const headerCells = _parseTableRow(line);\n i += 2; // skip header + separator\n const bodyRows = [];\n while (i < lines.length && /^\\|.+\\|/.test(lines[i])) {\n bodyRows.push(_parseTableRow(lines[i]));\n i++;\n }\n const thead = `<thead><tr>${headerCells.map((c) => `<th>${_inline(c)}</th>`).join('')}</tr></thead>`;\n const tbody = bodyRows.length\n ? `<tbody>${bodyRows.map((row) => `<tr>${row.map((c) => `<td>${_inline(c)}</td>`).join('')}</tr>`).join('')}</tbody>`\n : '';\n out.push(`<table>${thead}${tbody}</table>`);\n continue;\n }\n\n // ---- Paragraph: collect consecutive non-block lines ---------------------\n const paraLines = [];\n while (\n i < lines.length &&\n lines[i].trim() !== '' &&\n !/^(#{1,6} |> |[-*+] |\\d+\\. |```|---\\s*$|\\*{3}\\s*$|_{3}\\s*$)/.test(lines[i]) &&\n !/^\\|.+\\|/.test(lines[i])\n ) {\n paraLines.push(lines[i]);\n i++;\n }\n if (paraLines.length) {\n out.push(`<p>${_inline(paraLines.join(' '))}</p>`);\n }\n }\n\n return out.join('');\n}\n\n// ---------------------------------------------------------------------------\n// Inline formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Splits a GFM table row string into trimmed cell strings.\n * '| a | b | c |' → ['a', 'b', 'c']\n * @param {string} row\n * @returns {string[]}\n */\nfunction _parseTableRow(row) {\n return row\n .replace(/^\\|/, '')\n .replace(/\\|$/, '')\n .split('|')\n .map((c) => c.trim());\n}\n\nfunction _inline(text) {\n // Images before links (they share [] syntax)\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, (_, alt, src) =>\n `<img src=\"${_escAttr(src)}\" alt=\"${_escAttr(alt)}\" class=\"an-image\">`);\n // Links\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, label, href) =>\n `<a href=\"${_escAttr(href)}\">${_esc(label)}</a>`);\n // Bold + italic ***text***\n text = text.replace(/\\*{3}(.+?)\\*{3}/g, (_, c) => `<strong><em>${_esc(c)}</em></strong>`);\n text = text.replace(/_{3}(.+?)_{3}/g, (_, c) => `<strong><em>${_esc(c)}</em></strong>`);\n // Bold **text**\n text = text.replace(/\\*{2}(.+?)\\*{2}/g, (_, c) => `<strong>${_esc(c)}</strong>`);\n text = text.replace(/_{2}(.+?)_{2}/g, (_, c) => `<strong>${_esc(c)}</strong>`);\n // Italic *text* _text_\n text = text.replace(/\\*([^*\\n]+?)\\*/g, (_, c) => `<em>${_esc(c)}</em>`);\n text = text.replace(/_([^_\\n]+?)_/g, (_, c) => `<em>${_esc(c)}</em>`);\n // Strikethrough ~~text~~\n text = text.replace(/~~(.+?)~~/g, (_, c) => `<del>${_esc(c)}</del>`);\n // Inline code `code`\n text = text.replace(/`([^`]+)`/g, (_, c) => `<code>${_esc(c)}</code>`);\n return text;\n}\n\nfunction _esc(v) {\n return String(v)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nfunction _escAttr(v) {\n return String(v)\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n","/**\n * Editor.js - Core editing command module\n * Wraps all execCommand calls, undo/redo, and fires events via the context.\n * Inspired by Summernote's Editor module.\n */\n\nimport { History } from '../editing/History.js';\nimport * as Style from '../editing/Style.js';\nimport { insertTable } from '../editing/Table.js';\nimport { isModifier } from '../core/key.js';\nimport { handleKeydown } from '../editing/Typing.js';\nimport { on } from '../core/dom.js';\nimport { sanitiseHTML, sanitiseUrl } from '../core/sanitise.js';\nimport { markdownToHTML, htmlToMarkdown } from '../core/markdown.js';\n\nexport class Editor {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {History|null} */\n this._history = null;\n this._disposers = [];\n /** @type {number|null} Timer handle for debounced undo snapshot */\n this._snapshotTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n const editable = this.context.layoutInfo.editable;\n this._history = new History(editable, this.options.historyLimit || 100);\n this._bindEvents(editable);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n this._history = null;\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Event binding\n // ---------------------------------------------------------------------------\n\n _bindEvents(editable) {\n // Keyboard shortcuts\n const onKeydown = (event) => this._onKeydown(event);\n // Catch ALL content mutations: typing, IME, spellcheck, voice, drag-drop text.\n const onInput = () => this.afterCommand();\n // Hard-enforce maxChars / maxWords before content is mutated\n const onBeforeInput = (event) => this._enforceLimit(event);\n // Refresh toolbar on selection change, scoped to this editor\n const onSelChange = () => {\n if (!this.context._alive) return;\n const sel = window.getSelection();\n if (sel && sel.rangeCount > 0 && editable.contains(sel.anchorNode)) {\n this.context.invoke('toolbar.refresh');\n if (typeof this.options.onSelectionChange === 'function') {\n this.options.onSelectionChange(this.context);\n }\n }\n };\n\n // Checklist checkboxes are contenteditable=false so native clicks work;\n // hook afterCommand so the checked state is preserved in undo history.\n const onCheckboxClick = (e) => {\n if (e.target.type === 'checkbox' && e.target.closest('.an-checklist')) {\n this.afterCommand();\n }\n };\n\n // Guard: when cursor lands at the <li> element node of a checklist item\n // (before the checkbox), nudge it to the correct text position.\n //\n // mouseup: use caretRangeFromPoint / caretPositionFromPoint so the cursor\n // lands WHERE the user actually clicked (middle, end of text…).\n // keyup : arrow-key navigation may land at <li>[0]; move to start-of-text.\n const fixChecklistCursor = (event) => {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const r = sel.getRangeAt(0);\n if (!r.collapsed) return;\n const sc = r.startContainer;\n\n // Only act when cursor is at the <li> element node itself (not inside\n // a text node — the browser already placed it correctly in that case).\n if (sc.nodeType !== Node.ELEMENT_NODE) return;\n const li = sc.matches && sc.matches('.an-checklist li') ? sc : null;\n if (!li) return;\n const cb = li.querySelector('input[type=\"checkbox\"]');\n if (!cb) return;\n\n // For mouse events: ask the browser where the pointer landed so the\n // cursor respects the actual click position inside the text.\n if (event && event.type === 'mouseup') {\n let caret = null;\n if (document.caretRangeFromPoint) {\n caret = document.caretRangeFromPoint(event.clientX, event.clientY);\n } else if (document.caretPositionFromPoint) {\n const cp = document.caretPositionFromPoint(event.clientX, event.clientY);\n if (cp) {\n caret = document.createRange();\n caret.setStart(cp.offsetNode, cp.offset);\n }\n }\n // If the caret from point landed inside a text node of this li, use it\n if (caret && editable.contains(caret.startContainer) &&\n caret.startContainer !== li) {\n caret.collapse(true);\n sel.removeAllRanges();\n sel.addRange(caret);\n return;\n }\n }\n\n // Fallback (keyboard nav, or caretRangeFromPoint not available / landed\n // at li again): prefer the first text node after the checkbox so the\n // cursor renders at the padding-left edge (after the visual checkbox)\n // rather than at element-level where the browser may place it at x=0.\n const nr = document.createRange();\n let anchorNode = null;\n for (const child of li.childNodes) {\n if (child !== cb && child.nodeType === Node.TEXT_NODE) {\n anchorNode = child;\n break;\n }\n }\n if (anchorNode) {\n nr.setStart(anchorNode, 0);\n } else {\n nr.setStartAfter(cb);\n }\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n };\n\n const isReadOnly = () => this.context.layoutInfo.container.classList.contains('an-disabled');\n\n this._disposers.push(\n on(editable, 'keydown', onKeydown),\n on(editable, 'beforeinput', onBeforeInput),\n on(editable, 'input', onInput),\n on(document, 'selectionchange', onSelChange),\n on(editable, 'click', onCheckboxClick),\n on(editable, 'mouseup', fixChecklistCursor),\n on(editable, 'keyup', fixChecklistCursor),\n // Block drag-out and external drops in read-only mode.\n // D-1: Also block dragging of iframes and .an-video-wrapper elements in\n // edit mode — a user can inadvertently drag the iframe out of its wrapper\n // (making it playable/removable from contenteditable protection) by holding\n // the mouse and moving outside the wrapper before releasing.\n on(editable, 'dragstart', (e) => {\n if (isReadOnly()) { e.preventDefault(); return; }\n const target = e.target;\n if (target && (target.nodeName === 'IFRAME' ||\n (target.closest && target.closest('.an-video-wrapper')))) {\n e.preventDefault();\n }\n }),\n on(editable, 'drop', (e) => { if (isReadOnly()) e.preventDefault(); }),\n );\n\n // B-V: Re-apply superscript / subscript after IME composition ends.\n // Vietnamese and other IME-based inputs fire compositionstart/end around\n // the inserted characters. During composition the browser may place the\n // provisional text outside the current <sup>/<sub> element. When\n // compositionend fires we detect whether the cursor escaped the sup/sub\n // context and re-apply the command so the composed character stays inside.\n /** @type {string|null} 'superscript' | 'subscript' | null */\n let _compositionSupSub = null;\n const onCompositionStart = () => {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) { _compositionSupSub = null; return; }\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (node && node.closest) {\n if (node.closest('sup')) _compositionSupSub = 'superscript';\n else if (node.closest('sub')) _compositionSupSub = 'subscript';\n else _compositionSupSub = null;\n }\n };\n const onCompositionEnd = () => {\n const tag = _compositionSupSub;\n _compositionSupSub = null;\n if (!tag) return;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n const inContext = node && node.closest &&\n (tag === 'superscript' ? node.closest('sup') : node.closest('sub'));\n if (!inContext) {\n // The composed character escaped the sup/sub — re-apply the format.\n document.execCommand(tag);\n }\n };\n this._disposers.push(\n on(editable, 'compositionstart', onCompositionStart),\n on(editable, 'compositionend', onCompositionEnd),\n );\n }\n\n _onKeydown(event) {\n const editable = this.context.layoutInfo.editable;\n\n // Let Typing module handle special keys (Tab, Enter etc.)\n if (handleKeydown(event, editable, this.options)) return;\n\n // Built-in shortcuts\n if (isModifier(event, 'z') && !event.shiftKey) {\n event.preventDefault();\n this.undo();\n return;\n }\n if ((isModifier(event, 'z') && event.shiftKey) || isModifier(event, 'y')) {\n event.preventDefault();\n this.redo();\n return;\n }\n if (isModifier(event, 'b')) { event.preventDefault(); this.bold(); return; }\n if (isModifier(event, 'i')) { event.preventDefault(); this.italic(); return; }\n if (isModifier(event, 'u')) { event.preventDefault(); this.underline(); return; }\n if (isModifier(event, 'k')) { event.preventDefault(); this.context.invoke('linkDialog.show'); return; }\n\n // Ctrl+Shift+V — paste as plain text (signals Clipboard module)\n if (isModifier(event, 'v') && event.shiftKey) {\n this.context.invoke('clipboard.setForcePlain', true);\n return; // let the native paste event fire\n }\n\n // Show keyboard shortcuts dialog: Ctrl+Shift+/\n if (event.key === '/' && event.shiftKey && event.ctrlKey && !event.metaKey) {\n event.preventDefault();\n this.context.invoke('shortcutsDialog.show');\n return;\n }\n // Find: Ctrl+F\n if (isModifier(event, 'f')) {\n event.preventDefault();\n this.context.invoke('findReplace.show', 'find');\n return;\n }\n // Ctrl+H — Find & Replace\n if (isModifier(event, 'h')) {\n event.preventDefault();\n this.context.invoke('findReplace.show', 'replace');\n }\n // Ctrl+` — Inline Code\n if (isModifier(event, '`')) {\n event.preventDefault();\n this.inlineCode();\n }\n }\n\n // ---------------------------------------------------------------------------\n // Limit enforcement\n // ---------------------------------------------------------------------------\n\n /**\n * Called from beforeinput to block typing when char/word limits are reached.\n * Deletions and non-typing input types are always allowed.\n * @param {InputEvent} event\n */\n _enforceLimit(event) {\n const maxChars = this.options.maxChars || 0;\n const maxWords = this.options.maxWords || 0;\n if (!maxChars && !maxWords) return;\n\n const type = event.inputType || '';\n // Allow deletions, undo, redo and non-insert operations\n if (type.startsWith('delete') || type === 'historyUndo' || type === 'historyRedo') return;\n // Allow paste/drop — handled after the fact by Clipboard\n if (type === 'insertFromPaste' || type === 'insertFromDrop') return;\n // Only enforce for keyboard/IME/composition insertions\n if (!type.startsWith('insert')) return;\n\n const text = this.context.layoutInfo.editable.innerText || '';\n const chars = text.replace(/\\n/g, '').length;\n\n if (maxChars && chars >= maxChars) {\n event.preventDefault();\n if (typeof this.options.onCharLimitReached === 'function') {\n this.options.onCharLimitReached(this.context);\n }\n return;\n }\n\n // Word limit: block space / newline insertion when already at the limit\n if (maxWords && (event.data === ' ' || type === 'insertParagraph' || type === 'insertLineBreak')) {\n const words = text.trim() ? text.trim().split(/\\s+/).length : 0;\n if (words >= maxWords) {\n event.preventDefault();\n if (typeof this.options.onWordLimitReached === 'function') {\n this.options.onWordLimitReached(this.context);\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Post-command hook — records undo, fires change event\n // ---------------------------------------------------------------------------\n\n afterCommand() {\n // C4: Remove figure.an-figure elements whose <img> has been deleted so\n // orphaned figcaptions do not accumulate in the DOM.\n this._cleanOrphanedFigures();\n // Immediate: keep toolbar and statusbar in sync on every mutation.\n this.context.invoke('toolbar.refresh');\n this.context.invoke('statusbar.update');\n // Debounced: recording an undo snapshot and firing the change event require\n // a full innerHTML serialization. Batching rapid keystrokes prevents the\n // browser from re-serializing large content (e.g. embedded images) on every\n // single key press.\n this._scheduleSnapshot();\n }\n\n /**\n * Schedules a debounced undo snapshot + change event.\n * Resets the timer on each call so rapid typing produces one snapshot.\n */\n _scheduleSnapshot() {\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = setTimeout(() => {\n this._snapshotTimer = null;\n if (this._history) this._history.recordUndo();\n this.context.triggerEvent('change', this.getHTML());\n }, 400);\n }\n\n /**\n * C4: Removes figure.an-figure elements that no longer contain an <img>.\n * This happens when a user selects only the image (not the whole figure)\n * and deletes or replaces it, leaving a dangling figcaption.\n */\n _cleanOrphanedFigures() {\n const editable = this.context.layoutInfo.editable;\n editable.querySelectorAll('figure.an-figure').forEach((fig) => {\n if (!fig.querySelector('img')) {\n fig.parentNode.removeChild(fig);\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Focus management\n // ---------------------------------------------------------------------------\n\n focus() {\n const editable = this.context.layoutInfo.editable;\n editable.focus();\n }\n\n // ---------------------------------------------------------------------------\n // Content API\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the editor HTML content.\n * @returns {string}\n */\n getHTML() {\n // Strip zero-width spaces inserted after icons to allow caret placement.\n const raw = this.context.layoutInfo.editable.innerHTML.replace(/\\u200B/g, '');\n // Replace any blob: URLs (lightweight DOM references to pasted/dropped images)\n // with their original data URLs so the returned HTML is fully self-contained.\n return this.context.invoke('clipboard.resolveImages', raw) ?? raw;\n }\n\n /**\n * Sets the editor HTML content.\n * @param {string} html - HTML string (will be sanitised)\n */\n setHTML(html) {\n this.context.layoutInfo.editable.innerHTML = sanitiseHTML(html, { allowIframes: true });\n if (this._history) this._history.reset();\n this.afterCommand();\n }\n\n /**\n * Returns the editor plain text content.\n * @returns {string}\n */\n getText() {\n return this.context.layoutInfo.editable.innerText || '';\n }\n\n /**\n * Sets the editor content as plain text.\n * @param {string} text\n */\n setText(text) {\n this.context.layoutInfo.editable.textContent = text;\n if (this._history) this._history.reset();\n this.afterCommand();\n }\n\n /**\n * Clears the editor content.\n */\n clear() {\n this.setHTML('');\n }\n\n /**\n * Resets the undo/redo history stack.\n */\n clearHistory() {\n if (this._history) this._history.reset();\n }\n\n /**\n * Returns true when the editor has no meaningful content.\n * @returns {boolean}\n */\n isEmpty() {\n const text = (this.context.layoutInfo.editable.innerText || '')\n .trim()\n .replace(/\\u00a0/g, '');\n const hasMedia = !!this.context.layoutInfo.editable.querySelector('img, video, iframe, table');\n return !text && !hasMedia;\n }\n\n /**\n * Inserts HTML at the current cursor position.\n * @param {string} html\n */\n insertHTML(html) {\n if (!html) return;\n Style.execCommand('insertHTML', sanitiseHTML(html));\n this.afterCommand();\n }\n\n /**\n * Inserts plain text at the current cursor position.\n * @param {string} text\n */\n insertText(text) {\n if (!text) return;\n Style.execCommand('insertText', text);\n this.afterCommand();\n }\n\n /**\n * Sets editor content from a Markdown string.\n * @param {string} md\n */\n setMarkdown(md) {\n this.setHTML(markdownToHTML(md || ''));\n }\n\n /**\n * Returns the editor content as Markdown.\n * @returns {string}\n */\n getMarkdown() {\n return htmlToMarkdown(this.getHTML());\n }\n\n // ---------------------------------------------------------------------------\n // Undo / redo\n // ---------------------------------------------------------------------------\n\n undo() {\n if (this._history) {\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n this._history.undo();\n this.context.invoke('toolbar.refresh');\n this.context.invoke('statusbar.update');\n this.context.triggerEvent('change', this.getHTML());\n }\n }\n\n redo() {\n if (this._history) {\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n this._history.redo();\n this.context.invoke('toolbar.refresh');\n this.context.invoke('statusbar.update');\n this.context.triggerEvent('change', this.getHTML());\n }\n }\n\n canUndo() {\n return this._history ? this._history.canUndo() : false;\n }\n\n canRedo() {\n return this._history ? this._history.canRedo() : false;\n }\n\n // ---------------------------------------------------------------------------\n // Style commands (delegated to Style module)\n // ---------------------------------------------------------------------------\n\n bold() { Style.bold(); this.afterCommand(); }\n italic() { Style.italic(); this.afterCommand(); }\n underline() { Style.underline(); this.afterCommand(); }\n strikethrough() { Style.strikethrough(); this.afterCommand(); }\n superscript() { Style.superscript(); this.afterCommand(); }\n subscript() { Style.subscript(); this.afterCommand(); }\n justifyLeft() { Style.justifyLeft(); this.afterCommand(); }\n justifyCenter() { Style.justifyCenter(); this.afterCommand(); }\n justifyRight() { Style.justifyRight(); this.afterCommand(); }\n justifyFull() { Style.justifyFull(); this.afterCommand(); }\n indent() { Style.indent(); this.afterCommand(); }\n outdent() { Style.outdent(); this.afterCommand(); }\n insertUL() { Style.insertUnorderedList(); this.afterCommand(); }\n insertOL() { Style.insertOrderedList(); this.afterCommand(); }\n inlineCode() { Style.toggleInlineCode(this.context.layoutInfo.editable); this.afterCommand(); }\n toggleChecklist() { Style.toggleChecklist(); this.afterCommand(); }\n print() { this.context.print(); }\n\n /**\n * @param {string} tagName - e.g. 'h1', 'p', 'blockquote'\n */\n formatBlock(tagName) { Style.formatBlock(tagName); this.afterCommand(); }\n\n /**\n * @param {string} color\n */\n foreColor(color) { Style.foreColor(color); this.afterCommand(); }\n\n /**\n * @param {string} color\n */\n backColor(color) { Style.backColor(color); this.afterCommand(); }\n\n /**\n * @param {string} name\n */\n fontName(name) { Style.fontName(name); this.afterCommand(); }\n\n /**\n * @param {string} size - e.g. '14px'\n */\n fontSize(size) { Style.fontSize(size, this.context.layoutInfo.editable); this.afterCommand(); }\n\n // ---------------------------------------------------------------------------\n // Insert helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Inserts a horizontal rule at the cursor.\n */\n insertHr() {\n Style.execCommand('insertHorizontalRule');\n this.afterCommand();\n }\n\n /**\n * Creates a link at the current selection.\n * @param {string} url\n * @param {string} text\n * @param {boolean} [openInNewTab=false]\n */\n insertLink(url, text, openInNewTab = false) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const safeUrl = sanitiseUrl(url);\n if (!safeUrl) return;\n\n const hasText = sel.toString().trim().length > 0;\n if (!hasText) {\n const displayText = this._escapeAttr(text || safeUrl);\n Style.execCommand('insertHTML', `<a href=\"${this._escapeAttr(safeUrl)}\"${openInNewTab ? ' target=\"_blank\" rel=\"noopener noreferrer\"' : ''}>${displayText}</a>`);\n } else {\n Style.execCommand('createLink', safeUrl);\n if (openInNewTab) {\n const link = this._getClosestAnchor();\n if (link) {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n }\n }\n this.afterCommand();\n }\n\n /**\n * Removes the link from the selected anchor.\n */\n unlink() {\n Style.execCommand('unlink');\n this.afterCommand();\n }\n\n /**\n * Inserts an image.\n * @param {string} src - URL or data-URI\n * @param {string} [alt]\n */\n insertImage(src, alt = '', align = '') {\n const safeSrc = sanitiseUrl(src, { allowData: true });\n if (!safeSrc) return;\n const styleMap = {\n left: 'float:left;margin:0 1em 1em 0',\n center: 'display:block;margin:0 auto',\n right: 'float:right;margin:0 0 1em 1em',\n };\n const style = styleMap[align] || '';\n const styleAttr = style ? ` style=\"${style}\"` : '';\n Style.execCommand('insertHTML', `<img src=\"${this._escapeAttr(safeSrc)}\" alt=\"${this._escapeAttr(alt)}\" class=\"an-image\"${styleAttr}>`);\n this.afterCommand();\n }\n\n /**\n * Inserts a video embed (iframe or <video> element).\n * The html string is already validated/built by VideoDialog.\n * @param {string} html\n */\n insertVideo(html) {\n if (!html) return;\n Style.execCommand('insertHTML', html);\n this.afterCommand();\n }\n\n /**\n * Inserts a table.\n * @param {number} cols\n * @param {number} rows\n */\n insertTable(cols, rows) {\n insertTable(cols, rows, { headerRow: this.context.options.tableHeaderRow });\n this.afterCommand();\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n _getClosestAnchor() {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n let node = sel.getRangeAt(0).startContainer;\n while (node) {\n if (node.nodeName === 'A') return node;\n node = node.parentNode;\n }\n return null;\n }\n\n /**\n * Escapes a string for safe use inside an HTML attribute value.\n * @param {string} str\n * @returns {string}\n */\n _escapeAttr(str) {\n return String(str ?? '')\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n }\n\n // --- delegated to shared sanitise.js ---\n}\n","/**\n * Toolbar.js - Builds and manages the editor toolbar UI\n * Inspired by Summernote's Toolbar module — rewritten without jQuery\n */\n\nimport { createElement, on } from '../core/dom.js';\n\n// Module-level cache for FontAwesome detection.\n// Evaluated once per page load so all Toolbar instances on the same page agree\n// on whether the HOST PAGE included FA — regardless of whether IconDialog later\n// auto-injects its own FA <link> for the icon-picker glyph rendering.\nlet _faPageLevelReady = null;\n\n// ---------------------------------------------------------------------------\n// Module-level icon lookup tables — built once, shared across all instances.\n// Previously these were re-created inside _createButton() on every button\n// render, producing O(buttons × map-size) allocations per toolbar init.\n// ---------------------------------------------------------------------------\nconst _S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\nconst _svgWrap = (paths) =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${_S} style=\"display:block\">${paths}</svg>`;\n\nconst _SVG_MAP = new Map([\n // Format\n ['bold', _svgWrap('<path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/>')],\n ['italic', _svgWrap('<line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/>')],\n ['underline', _svgWrap('<path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/>')],\n ['strikethrough', _svgWrap('<path d=\"M17.3 12H6.7\"/><path d=\"M10 6.5C10 5.1 11.1 4 12.5 4c1.4 0 2.5 1.1 2.5 2.5 0 .8-.4 1.5-1 2\"/><path d=\"M14 17.5C14 19 12.9 20 11.5 20 10.1 20 9 18.9 9 17.5c0-.8.4-1.5 1-2\"/>')],\n ['superscript', _svgWrap('<path d=\"m4 19 8-8\"/><path d=\"m12 19-8-8\"/><path d=\"M20 12h-4c0-1.5.44-2 1.5-2.5S20 8.33 20 7.25C20 6 19 5 17.5 5S15 6 15 7\"/>')],\n ['subscript', _svgWrap('<path d=\"m4 5 8 8\"/><path d=\"m12 5-8 8\"/><path d=\"M20 21h-4c0-1.5.44-2 1.5-2.5S20 17.33 20 16.25C20 15 19 14 17.5 14S15 15 15 16\"/>')],\n // Alignment\n ['align-left', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"/>')],\n ['align-center', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"18\" y1=\"12\" x2=\"6\" y2=\"12\"/><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"/>')],\n ['align-right', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"/>')],\n ['align-justify', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"12\" x2=\"3\" y2=\"12\"/><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"/>')],\n // Lists\n ['list-ul', _svgWrap('<line x1=\"9\" y1=\"6\" x2=\"20\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"20\" y2=\"12\"/><line x1=\"9\" y1=\"18\" x2=\"20\" y2=\"18\"/><circle cx=\"4\" cy=\"6\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"18\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/>')],\n ['list-ol', _svgWrap('<line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/><path d=\"M4 6h1V3\"/><path d=\"M4 10h2l-2 2h2\"/><path d=\"M4 16.5A1.5 1.5 0 0 1 5.5 15a1.5 1.5 0 0 1 0 3H4\"/>')],\n ['indent', _svgWrap('<polyline points=\"3 8 7 12 3 16\"/><line x1=\"21\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"21\" y1=\"6\" x2=\"11\" y2=\"6\"/><line x1=\"21\" y1=\"18\" x2=\"11\" y2=\"18\"/>')],\n ['outdent', _svgWrap('<polyline points=\"7 8 3 12 7 16\"/><line x1=\"21\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"21\" y1=\"6\" x2=\"11\" y2=\"6\"/><line x1=\"21\" y1=\"18\" x2=\"11\" y2=\"18\"/>')],\n // History\n ['undo', _svgWrap('<path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/>')],\n ['redo', _svgWrap('<path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/>')],\n // Insert\n ['minus', _svgWrap('<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>')],\n ['link', _svgWrap('<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>')],\n ['image', _svgWrap('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>')],\n ['video', _svgWrap('<polygon points=\"23 7 16 12 23 17 23 7\"/><rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\"/>')],\n ['table', _svgWrap('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/>')],\n ['emoji', _svgWrap('<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8.5 14.5s1.5 2.5 3.5 2.5 3.5-2.5 3.5-2.5\"/><circle cx=\"9\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>')],\n ['icon', _svgWrap('<circle cx=\"8\" cy=\"8\" r=\"3\"/><circle cx=\"16\" cy=\"8\" r=\"3\"/><rect x=\"5\" y=\"13\" width=\"6\" height=\"6\" rx=\"1\"/><rect x=\"13\" y=\"13\" width=\"6\" height=\"6\" rx=\"1\"/>')],\n // View\n ['code', _svgWrap('<polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/>')],\n ['expand', _svgWrap('<polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/>')],\n // Color pickers\n ['foreColor', _svgWrap('<path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/>')],\n ['backColor', _svgWrap('<path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/>')],\n ['keyboard', _svgWrap('<rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"2\"/><line x1=\"6\" y1=\"10\" x2=\"6\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"10\" y1=\"10\" x2=\"10\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"14\" y1=\"10\" x2=\"14\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"18\" y1=\"10\" x2=\"18\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"8\" y1=\"14\" x2=\"16\" y2=\"14\" stroke-width=\"2\"/>')],\n ['caption', _svgWrap('<rect x=\"3\" y=\"3\" width=\"18\" height=\"11\" rx=\"2\"/><line x1=\"6\" y1=\"18\" x2=\"18\" y2=\"18\"/><line x1=\"9\" y1=\"21\" x2=\"15\" y2=\"21\"/>')],\n ['remove-format', _svgWrap('<path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/>')],\n ['direction', _svgWrap('<path d=\"M12 20V4\"/><path d=\"m9 7-3 3 3 3\"/><path d=\"M4 10h8\"/><path d=\"m15 7 3 3-3 3\"/><path d=\"M20 10h-8\"/>')],\n ['search', _svgWrap('<circle cx=\"11\" cy=\"11\" r=\"7\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/>')],\n ['find-replace', _svgWrap('<circle cx=\"10\" cy=\"10\" r=\"6\"/><line x1=\"18\" y1=\"18\" x2=\"14.35\" y2=\"14.35\"/><path d=\"M16 19h6\"/><path d=\"M19 16v6\"/>')],\n ['inline-code', _svgWrap('<path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\"/><path d=\"M16 3h1a2 2 0 0 1 2 2v5c0 1.1.9 2 2 2a2 2 0 0 1-2 2v5a2 2 0 0 1-2 2h-1\"/>')],\n ['checklist', _svgWrap('<rect x=\"3\" y=\"4\" width=\"5\" height=\"5\" rx=\"1\"/><path d=\"m4 6.5 1 1 2-2\"/><rect x=\"3\" y=\"13\" width=\"5\" height=\"5\" rx=\"1\"/><line x1=\"10\" y1=\"6.5\" x2=\"21\" y2=\"6.5\"/><line x1=\"10\" y1=\"15.5\" x2=\"21\" y2=\"15.5\"/>')],\n ['print', _svgWrap('<path d=\"M6 9V2h12v7\"/><path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\"/><rect x=\"6\" y=\"14\" width=\"12\" height=\"8\"/>')],\n]);\n\nconst _FA_MAP = new Map([\n ['bold', 'fa-bold'],\n ['italic', 'fa-italic'],\n ['underline', 'fa-underline'],\n ['strikethrough', 'fa-strikethrough'],\n ['superscript', 'fa-superscript'],\n ['subscript', 'fa-subscript'],\n ['align-left', 'fa-align-left'],\n ['align-center', 'fa-align-center'],\n ['align-right', 'fa-align-right'],\n ['align-justify', 'fa-align-justify'],\n ['list-ul', 'fa-list-ul'],\n ['list-ol', 'fa-list-ol'],\n ['indent', 'fa-indent'],\n ['outdent', 'fa-outdent'],\n ['undo', 'fa-rotate-left'],\n ['redo', 'fa-rotate-right'],\n ['minus', 'fa-minus'],\n ['link', 'fa-link'],\n ['image', 'fa-image'],\n ['code', 'fa-code'],\n ['expand', 'fa-expand'],\n ['emoji', 'fa-face-smile'],\n ['icon', 'fa-icons'],\n ['foreColor', 'fa-font'],\n ['backColor', 'fa-highlighter'],\n ['keyboard', 'fa-keyboard'],\n ['remove-format', 'fa-remove-format'],\n ['direction', 'fa-arrow-right-arrow-left'],\n ['search', 'fa-magnifying-glass'],\n ['find-replace', 'fa-magnifying-glass-plus'],\n ['inline-code', 'fa-code'],\n ['checklist', 'fa-list-check'],\n ['print', 'fa-print'],\n]);\n\nexport class Toolbar {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this.el = null;\n /** @type {Array<() => void>} disposers */\n this._disposers = [];\n /** @type {Array<() => void>} closers for all open color picker popups */\n this._colorPickerClosers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this.el = createElement('div', { class: 'an-toolbar' });\n // Detect FontAwesome once at toolbar build time to avoid re-querying the DOM\n // for every button rendered.\n this._faReady = this._detectFontAwesome();\n this._buildButtons();\n this._btnMap = new Map((this.options.toolbar || []).flat().map((b) => [b.name, b]));\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this.el && this.el.parentNode) {\n this.el.parentNode.removeChild(this.el);\n }\n this.el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildButtons() {\n const toolbar = this.options.toolbar || [];\n // Build into a DocumentFragment so all groups are appended in a single\n // DOM operation, avoiding one reflow per group.\n const fragment = document.createDocumentFragment();\n toolbar.forEach((group) => {\n const groupEl = createElement('div', { class: 'an-btn-group' });\n group.forEach((btnDef) => {\n let el;\n if (btnDef.type === 'select') el = this._createSelect(btnDef);\n else if (btnDef.type === 'grid') el = this._createGridPicker(btnDef);\n else if (btnDef.type === 'colorpicker') el = this._createColorPicker(btnDef);\n else el = this._createButton(btnDef);\n groupEl.appendChild(el);\n });\n fragment.appendChild(groupEl);\n });\n this.el.appendChild(fragment);\n }\n\n /**\n * Creates a table-grid picker button with a hoverable row/col selector popup.\n * @param {import('./Buttons.js').ButtonDef} def\n * @returns {HTMLDivElement}\n */\n _createGridPicker(def) {\n const ROWS = 10;\n const COLS = 10;\n\n const wrap = createElement('div', { class: 'an-table-picker-wrap' });\n\n const useBootstrap = !!this.options.useBootstrap;\n const baseClass = useBootstrap\n ? (this.options.toolbarButtonClass || 'btn btn-sm btn-light')\n : 'an-btn';\n const btn = createElement('button', {\n type: 'button',\n class: baseClass,\n title: this.context.locale.toolbar[def.name] || def.tooltip || '',\n 'data-btn': def.name,\n 'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,\n 'aria-haspopup': 'true',\n 'aria-expanded': 'false',\n });\n\n // Set icon — inline SVG (table) with optional FontAwesome fallback\n if (this._faReady) {\n const faPrefix = this.options.fontAwesomeClass || 'fas';\n btn.innerHTML = `<i class=\"${faPrefix} fa-table\" aria-hidden=\"true\"></i>`;\n } else {\n const S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\n btn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${S} style=\"display:block\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>`;\n }\n\n // Popup\n const popup = createElement('div', {\n class: 'an-table-picker-popup',\n role: 'dialog',\n 'aria-label': 'Select table size',\n });\n const grid = createElement('div', { class: 'an-table-grid' });\n const label = createElement('div', { class: 'an-table-label' });\n label.textContent = this.context.locale.toolbar.insertTableLabel || 'Insert Table';\n\n const cells = [];\n for (let r = 1; r <= ROWS; r++) {\n for (let c = 1; c <= COLS; c++) {\n const cell = createElement('div', {\n class: 'an-table-cell',\n 'data-row': String(r),\n 'data-col': String(c),\n });\n cells.push(cell);\n grid.appendChild(cell);\n }\n }\n\n popup.appendChild(grid);\n popup.appendChild(label);\n\n let isOpen = false;\n\n const setHighlight = (rows, cols) => {\n cells.forEach((cell) => {\n const r = +cell.getAttribute('data-row');\n const c = +cell.getAttribute('data-col');\n cell.classList.toggle('active', r <= rows && c <= cols);\n });\n label.textContent = (rows && cols) ? `${rows} × ${cols}` : (this.context.locale.toolbar.insertTableLabel || 'Insert Table');\n };\n\n const openPopup = () => {\n isOpen = true;\n popup.style.display = 'block';\n btn.setAttribute('aria-expanded', 'true');\n };\n\n const closePopup = () => {\n isOpen = false;\n popup.style.display = 'none';\n btn.setAttribute('aria-expanded', 'false');\n setHighlight(0, 0);\n };\n\n const d1 = on(btn, 'click', (e) => {\n e.stopPropagation();\n if (isOpen) closePopup(); else openPopup();\n });\n\n const d2 = on(grid, 'mouseover', (e) => {\n const cell = e.target.closest('.an-table-cell');\n if (!cell) return;\n setHighlight(+cell.getAttribute('data-row'), +cell.getAttribute('data-col'));\n });\n\n const d3 = on(grid, 'mouseleave', () => setHighlight(0, 0));\n\n const d4 = on(grid, 'click', (e) => {\n const cell = e.target.closest('.an-table-cell');\n if (!cell) return;\n const rows = +cell.getAttribute('data-row');\n const cols = +cell.getAttribute('data-col');\n closePopup();\n this.context.invoke('editor.focus');\n def.action(this.context, rows, cols);\n });\n\n const d5 = on(document, 'click', () => { if (isOpen) closePopup(); });\n\n this._disposers.push(d1, d2, d3, d4, d5);\n\n wrap.appendChild(btn);\n wrap.appendChild(popup);\n return wrap;\n }\n\n /**\n * Creates a split color-picker widget:\n * [icon + strip | ▾] — left applies current color, right opens swatch popup.\n * @param {{ name: string, type: 'colorpicker', tooltip: string, defaultColor: string, action: Function }} def\n * @returns {HTMLDivElement}\n */\n _createColorPicker(def) {\n const PRESETS = [\n // Grayscale\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n // Saturated\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n // Pastel\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\n ];\n\n let currentColor = def.defaultColor || '#000000';\n\n const wrap = createElement('div', { class: 'an-color-picker-wrap' });\n\n const useBootstrap = !!this.options.useBootstrap;\n const baseClass = useBootstrap ? (this.options.toolbarButtonClass || 'btn btn-sm btn-light') : 'an-btn';\n\n // ---- Apply button (icon + color strip) ----\n const applyBtn = createElement('button', {\n type: 'button',\n class: `${baseClass} an-color-btn`,\n title: this.context.locale.toolbar[def.name] || def.tooltip || '',\n 'data-btn': def.name,\n 'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,\n });\n\n const S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\n const iconSvg = def.name === 'foreColor'\n ? `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${S} style=\"display:block\"><path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/></svg>`\n : `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${S} style=\"display:block\"><path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/></svg>`;\n\n applyBtn.innerHTML = iconSvg;\n const strip = createElement('span', { class: 'an-color-strip' });\n strip.style.background = currentColor;\n applyBtn.appendChild(strip);\n\n // ---- Arrow button (open popup) ----\n const arrowBtn = createElement('button', {\n type: 'button',\n class: `${baseClass} an-color-arrow`,\n title: def.name === 'foreColor'\n ? (this.context.locale.toolbar.chooseTextColor || 'Choose text color')\n : (this.context.locale.toolbar.chooseHighlightColor || 'Choose highlight color'),\n 'aria-haspopup': 'true',\n 'aria-expanded': 'false',\n });\n arrowBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"8\" height=\"8\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" style=\"display:block\"><path d=\"M7 10l5 5 5-5H7z\"/></svg>`;\n\n // ---- Popup ----\n const popup = createElement('div', { class: 'an-color-popup' });\n popup.style.display = 'none';\n\n const swatches = createElement('div', { class: 'an-color-swatches' });\n const userSwatches = Array.isArray(this.options.colorSwatches) ? this.options.colorSwatches : [];\n const allColors = [...new Set([...userSwatches, ...PRESETS])];\n allColors.forEach((color) => {\n const sw = createElement('div', { class: 'an-color-swatch', title: color, 'data-color': color });\n sw.style.background = color;\n swatches.appendChild(sw);\n });\n\n const customRow = createElement('div', { class: 'an-color-custom' });\n const colorInput = createElement('input', { type: 'color', value: currentColor, title: this.context.locale.toolbar.customColor || 'Custom color' });\n const customLabel = createElement('span', {}, [this.context.locale.toolbar.customColor || 'Custom color']);\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n\n popup.appendChild(swatches);\n popup.appendChild(customRow);\n\n // ---- State ----\n let isOpen = false;\n /** @type {Range|null} saved selection range before popup opens */\n let savedRange = null;\n\n const saveSelection = () => {\n const sel = window.getSelection();\n savedRange = (sel && sel.rangeCount) ? sel.getRangeAt(0).cloneRange() : null;\n };\n\n const restoreSelection = () => {\n if (!savedRange) return;\n try {\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(savedRange);\n } catch (_) {\n // Range target may be detached if DOM changed while popup was open\n }\n };\n\n const openPopup = () => {\n // Close any other open color picker before opening this one\n this._colorPickerClosers.forEach((fn) => { if (fn !== closePopup) fn(); });\n saveSelection();\n isOpen = true;\n // Use fixed positioning so the popup escapes any overflow-clipping ancestor\n // (notably toolbar scroll mode, where overflow-x:auto coerces overflow-y)\n const rect = arrowBtn.getBoundingClientRect();\n const popupMinW = 184;\n let left = rect.left;\n if (left + popupMinW > window.innerWidth) left = rect.right - popupMinW;\n popup.style.top = `${rect.bottom + 4}px`;\n popup.style.left = `${Math.max(4, left)}px`;\n popup.style.display = 'block';\n arrowBtn.setAttribute('aria-expanded', 'true');\n };\n\n const closePopup = () => {\n isOpen = false;\n popup.style.display = 'none';\n popup.style.top = '';\n popup.style.left = '';\n arrowBtn.setAttribute('aria-expanded', 'false');\n };\n\n const applyColor = (color) => {\n currentColor = color;\n strip.style.background = color;\n colorInput.value = color;\n restoreSelection();\n def.action(this.context, color);\n this.context.invoke('editor.afterCommand');\n closePopup();\n };\n\n const d1 = on(applyBtn, 'click', (e) => {\n e.preventDefault();\n restoreSelection();\n def.action(this.context, currentColor);\n this.context.invoke('editor.afterCommand');\n });\n\n const d2 = on(arrowBtn, 'mousedown', (e) => {\n // Prevent editor blur so selection is preserved when the popup opens\n e.preventDefault();\n });\n\n const d2b = on(arrowBtn, 'click', (e) => {\n e.stopPropagation();\n if (isOpen) closePopup(); else openPopup();\n });\n\n const d3 = on(swatches, 'mousedown', (e) => {\n // Prevent blur before the click handler fires\n e.preventDefault();\n });\n\n const d3b = on(swatches, 'click', (e) => {\n const sw = e.target.closest('.an-color-swatch');\n if (sw) applyColor(sw.dataset.color);\n });\n\n const d4 = on(colorInput, 'change', (e) => {\n applyColor(e.target.value);\n });\n\n const d5 = on(document, 'click', (e) => {\n // popup is in document.body, not inside wrap — check both\n if (isOpen && !wrap.contains(e.target) && !popup.contains(e.target)) closePopup();\n });\n\n const d6 = on(popup, 'click', (e) => e.stopPropagation());\n\n // Close the popup when the viewport scrolls or resizes so the fixed-position\n // popup doesn't drift away from the button it belongs to.\n const onScrollResize = () => { if (isOpen) closePopup(); };\n document.addEventListener('scroll', onScrollResize, { passive: true, capture: true });\n window.addEventListener('resize', onScrollResize, { passive: true });\n\n this._disposers.push(d1, d2, d2b, d3, d3b, d4, d5, d6,\n () => document.removeEventListener('scroll', onScrollResize, { capture: true }),\n () => window.removeEventListener('resize', onScrollResize),\n // Remove popup from body on editor destroy\n () => { if (popup.parentNode) popup.parentNode.removeChild(popup); },\n );\n\n // Register this popup's closer so other color pickers can close it\n this._colorPickerClosers.push(closePopup);\n this._disposers.push(() => {\n const idx = this._colorPickerClosers.indexOf(closePopup);\n if (idx !== -1) this._colorPickerClosers.splice(idx, 1);\n });\n\n // Append popup to document.body so it escapes all overflow-clipping and\n // contain:layout ancestors (contain:layout makes the container a fixed-pos\n // containing block per the CSS Contain spec, breaking viewport coordinates).\n wrap.appendChild(applyBtn);\n wrap.appendChild(arrowBtn);\n document.body.appendChild(popup);\n return wrap;\n }\n\n /**\n * Creates a <select> dropdown for font-family (or similar) options.\n * @param {import('./Buttons.js').DropdownDef} def\n * @returns {HTMLSelectElement}\n */\n _createSelect(def) {\n const items = (def.name === 'fontFamily')\n ? (this.options.fontFamilies || [])\n : (def.items || []);\n\n const cls = def.selectClass ? `an-select ${def.selectClass}` : 'an-select';\n const select = createElement('select', {\n class: cls,\n title: this.context.locale.toolbar[def.name] || def.tooltip || '',\n 'data-btn': def.name,\n 'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,\n });\n\n // Blank \"placeholder\" option (non-selectable header)\n const placeholderText = this.context.locale.toolbar[def.name + 'Placeholder'] || def.placeholder || 'Font';\n const placeholder = createElement('option', { value: '', disabled: '', hidden: '' }, [placeholderText]);\n select.appendChild(placeholder);\n\n items.forEach((item) => {\n const value = (typeof item === 'object') ? item.value : item;\n const label = (typeof item === 'object')\n ? (def.name === 'paragraphStyle'\n ? ((this.context.locale.toolbar.paragraphItems || {})[item.value] || item.label)\n : item.label)\n : item;\n const isHeader = (typeof item === 'object') && !!item.disabled;\n const attrs = { value };\n if (isHeader) attrs.disabled = '';\n const opt = createElement('option', attrs, [label]);\n // Only apply fontFamily face preview on real (non-header) entries\n if (def.name === 'fontFamily' && !isHeader) opt.style.fontFamily = value;\n select.appendChild(opt);\n });\n\n // Save the editor selection when the user starts interacting with the\n // dropdown (mousedown fires before the editor loses focus). When the\n // change handler runs, focus has moved to the <select>; we restore the\n // saved range so execCommand / fontSize() act on the intended text.\n /** @type {Range|null} */\n let _savedRange = null;\n const dMousedown = on(select, 'mousedown', () => {\n const sel = window.getSelection();\n _savedRange = (sel && sel.rangeCount) ? sel.getRangeAt(0).cloneRange() : null;\n });\n\n const disposer = on(select, 'change', (e) => {\n const value = /** @type {HTMLSelectElement} */ (e.target).value;\n const selectedOpt = /** @type {HTMLSelectElement} */ (e.target).options[/** @type {HTMLSelectElement} */ (e.target).selectedIndex];\n if (!value || selectedOpt.disabled) return;\n this.context.invoke('editor.focus');\n // Restore selection saved on mousedown so the action targets the correct text.\n if (_savedRange) {\n try {\n const sel = window.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(_savedRange); }\n } catch (_) { /* range may be stale if DOM changed */ }\n }\n def.action(this.context, value);\n this.context.invoke('editor.afterCommand');\n });\n\n this._disposers.push(dMousedown, disposer);\n return select;\n }\n\n /**\n * @param {import('./Buttons.js').ButtonDef} btnDef\n * @returns {HTMLButtonElement}\n */\n _createButton(btnDef) {\n // Determine classes based on whether the consumer wants Bootstrap styling\n const useBootstrap = !!this.options.useBootstrap;\n const baseClass = useBootstrap ? (this.options.toolbarButtonClass || 'btn btn-sm btn-light') : `an-btn`;\n const extra = btnDef.className ? ` ${btnDef.className}` : '';\n const classAttr = `${baseClass}${extra}`;\n\n const btn = createElement('button', {\n type: 'button',\n class: classAttr,\n title: this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || '',\n 'data-btn': btnDef.name,\n 'aria-label': this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || btnDef.name,\n });\n\n // Render icon: prefer FontAwesome if enabled; otherwise fall back to SVG or text.\n const faPrefix = this.options.fontAwesomeClass || 'fas';\n const useFaNow = this._faReady;\n if (useFaNow) {\n const faName = _FA_MAP.get(btnDef.icon) || _FA_MAP.get(btnDef.name) || null;\n if (faName) {\n btn.innerHTML = `<i class=\"${faPrefix} ${faName}\" aria-hidden=\"true\"></i>`;\n } else if (_SVG_MAP.has(btnDef.icon)) {\n btn.innerHTML = _SVG_MAP.get(btnDef.icon);\n } else {\n btn.textContent = btnDef.icon || btnDef.name;\n }\n } else {\n // FontAwesome absent: use SVG fallback when available\n if (_SVG_MAP.has(btnDef.icon)) {\n btn.innerHTML = _SVG_MAP.get(btnDef.icon);\n } else if (_SVG_MAP.has(btnDef.name)) {\n btn.innerHTML = _SVG_MAP.get(btnDef.name);\n } else {\n btn.textContent = btnDef.icon || btnDef.name;\n }\n }\n\n const disposer = on(btn, 'click', (event) => {\n event.preventDefault();\n // Restore focus to the editor before executing the action\n this.context.invoke('editor.focus');\n btnDef.action(this.context);\n this.context.invoke('editor.afterCommand');\n this.refresh();\n });\n\n this._disposers.push(disposer);\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // FontAwesome detection (run once at initialize time)\n // ---------------------------------------------------------------------------\n\n _detectFontAwesome() {\n if (!this.options.useFontAwesome) return false;\n // Return cached result when available. This ensures that a later-initialised\n // toolbar sees the same detection state as the first one — even if IconDialog\n // has since injected its own FA <link> into <head> for the icon-picker UI.\n if (_faPageLevelReady !== null) return _faPageLevelReady;\n if (document.querySelector('.fa, .fas, .far, .fal, .fab, .fa-solid')) {\n _faPageLevelReady = true;\n return true;\n }\n // Exclude the editor-self-injected link (id='an-fontawesome-css') so it doesn't\n // count as \"the host page loaded FA\" for toolbar icon rendering purposes.\n const links = Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]'))\n .filter((l) => l.id !== 'an-fontawesome-css')\n .map((l) => l.href || '').join(' ');\n _faPageLevelReady = /fontawesome|font-awesome|use\\.fontawesome|all\\.css/.test(links);\n return _faPageLevelReady;\n }\n\n // ---------------------------------------------------------------------------\n // State refresh (active / disabled states)\n // ---------------------------------------------------------------------------\n\n refresh() {\n if (!this.el) return;\n const btnMap = this._btnMap || new Map();\n\n // Sync button active states\n this.el.querySelectorAll('button[data-btn]').forEach((btn) => {\n const def = btnMap.get(btn.getAttribute('data-btn'));\n if (def && typeof def.isActive === 'function') {\n btn.classList.toggle('active', !!def.isActive(this.context));\n }\n if (def && typeof def.isDisabled === 'function') {\n btn.disabled = !!def.isDisabled(this.context);\n }\n });\n\n // Sync select dropdowns (e.g. font family) with current cursor position\n this.el.querySelectorAll('select[data-btn]').forEach((select) => {\n const def = btnMap.get(select.getAttribute('data-btn'));\n if (!def || typeof def.getValue !== 'function') return;\n // queryCommandValue returns the font name, possibly quoted — strip quotes\n let raw = (def.getValue(this.context) || '').replace(/[\"']/g, '').trim();\n // Fallback: when no selection/font set, use the configured default font\n if (!raw) {\n raw = this.options.defaultFontFamily\n || (this.options.fontFamilies && this.options.fontFamilies[0])\n || '';\n }\n // Try to match against available options (case-insensitive)\n const matched = Array.from(select.options).find(\n (opt) => opt.value && opt.value.toLowerCase() === raw.toLowerCase()\n );\n select.value = matched ? matched.value : '';\n });\n }\n\n /**\n * Shows the toolbar.\n */\n show() {\n if (this.el) this.el.style.display = '';\n }\n\n /**\n * Hides the toolbar.\n */\n hide() {\n if (this.el) this.el.style.display = 'none';\n }\n}\n","/**\n * Statusbar.js - Displays word count, character count and resize handle\n * Inspired by Summernote's Statusbar module — rewritten without jQuery\n */\n\nimport { createElement, on } from '../core/dom.js';\nimport { debounce } from '../core/func.js';\n\n// Cache the segmenter instance at module level to avoid per-call allocation\nconst _segmenter =\n typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function'\n ? new Intl.Segmenter(undefined, { granularity: 'word' })\n : null;\n\n/**\n * Count words in a string, CJK-aware.\n * Uses Intl.Segmenter (Chromium 87+, Firefox 125+, Safari 17+) when available,\n * falling back to a simple whitespace split for older environments.\n * @param {string} text\n * @returns {number}\n */\nfunction _countWords(text) {\n const trimmed = text.trim();\n if (!trimmed) return 0;\n if (_segmenter) {\n let count = 0;\n for (const seg of _segmenter.segment(trimmed)) {\n if (seg.isWordLike) count++;\n }\n return count;\n }\n // Fallback: split on whitespace\n return trimmed.split(/\\s+/).length;\n}\n\n/**\n * Toggles warning/exceeded CSS classes on a count element.\n * @param {HTMLElement} el\n * @param {number} current\n * @param {number} limit 0 = no limit\n */\nfunction _applyLimitClass(el, current, limit) {\n if (!limit) {\n el.classList.remove('an-count-warn', 'an-count-exceeded');\n return;\n }\n if (current > limit) {\n el.classList.add('an-count-exceeded');\n el.classList.remove('an-count-warn');\n } else if (current >= limit * 0.9) {\n el.classList.add('an-count-warn');\n el.classList.remove('an-count-exceeded');\n } else {\n el.classList.remove('an-count-warn', 'an-count-exceeded');\n }\n}\n\nexport class Statusbar {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this.el = null;\n this._disposers = [];\n /** @type {HTMLElement|null} */\n this._wordCountEl = null;\n /** @type {HTMLElement|null} */\n this._charCountEl = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this.el = createElement('div', { class: 'an-statusbar' });\n\n // Resize handle\n if (this.options.resizable !== false) {\n const handle = createElement('div', {\n class: 'an-resize-handle',\n title: this.context.locale.statusbar.resizeHandle,\n 'aria-hidden': 'true',\n });\n this._bindResize(handle);\n this.el.appendChild(handle);\n }\n\n // Counters\n this._wordCountEl = createElement('span', { class: 'an-word-count' });\n this._charCountEl = createElement('span', { class: 'an-char-count' });\n const info = createElement('div', { class: 'an-status-info' });\n info.appendChild(this._wordCountEl);\n info.appendChild(this._charCountEl);\n this.el.appendChild(info);\n\n this._bindContentEvents();\n this.update();\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dragDisposers) {\n this._dragDisposers.forEach((d) => d());\n this._dragDisposers = null;\n }\n if (this.el && this.el.parentNode) {\n this.el.parentNode.removeChild(this.el);\n }\n this.el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Resize logic\n // ---------------------------------------------------------------------------\n\n _bindResize(handle) {\n let startY = 0;\n let startH = 0;\n // Resize the container (flex column parent) so that the editable — which\n // has flex:1 / flex-basis:0 — automatically fills the remaining space.\n // Setting height directly on a flex:1 item has no effect because the flex\n // algorithm ignores the height property when flex-basis is non-auto.\n const containerEl = this.context.layoutInfo.container;\n\n const applyDelta = (clientY) => {\n const delta = clientY - startY;\n // Compute the true minimum: fixed elements (toolbar + statusbar) must fit\n // inside the container. Sum the offsetHeight of every child that is NOT\n // the editable area, then add a small floor so the editable stays visible.\n const MIN_EDITABLE = 40;\n const fixedH = Array.from(containerEl.children)\n .filter(child => !child.classList.contains('an-editable'))\n .reduce((sum, child) => sum + child.offsetHeight, 0);\n const trueMin = Math.max(this.options.minHeight || 100, fixedH + MIN_EDITABLE);\n containerEl.style.height = `${Math.max(trueMin, startH + delta)}px`;\n };\n\n // Mouse drag\n const onMouseMove = (event) => applyDelta(event.clientY);\n\n const onMouseUp = () => {\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n this._dragDisposers = null;\n };\n\n const onMouseDown = (event) => {\n startY = event.clientY;\n startH = containerEl.offsetHeight;\n // Clear the editable's inline min-height so the flex layout can compress\n // it freely once the container has a fixed height. Without this, the\n // editable's min-height (set from options.height) overflows the container\n // when the user drags the handle to a size smaller than that value.\n this.context.layoutInfo.editable.style.minHeight = '';\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n // Track drag-phase listeners so destroy() can remove them mid-drag\n this._dragDisposers = [\n () => document.removeEventListener('mousemove', onMouseMove),\n () => document.removeEventListener('mouseup', onMouseUp),\n ];\n event.preventDefault();\n };\n\n // Touch drag\n const onTouchMove = (event) => {\n const touch = event.touches[0];\n if (touch) { event.preventDefault(); applyDelta(touch.clientY); }\n };\n\n const onTouchEnd = () => {\n document.removeEventListener('touchmove', onTouchMove);\n document.removeEventListener('touchend', onTouchEnd);\n this._dragDisposers = null;\n };\n\n const onTouchStart = (event) => {\n const touch = event.touches[0];\n if (!touch) return;\n startY = touch.clientY;\n startH = containerEl.offsetHeight;\n // Same as onMouseDown: clear editable min-height so flex can compress it\n this.context.layoutInfo.editable.style.minHeight = '';\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', onTouchEnd);\n this._dragDisposers = [\n () => document.removeEventListener('touchmove', onTouchMove),\n () => document.removeEventListener('touchend', onTouchEnd),\n ];\n };\n\n const d1 = on(handle, 'mousedown', onMouseDown);\n const d2 = on(handle, 'touchstart', onTouchStart);\n this._disposers.push(d1, d2);\n }\n\n // ---------------------------------------------------------------------------\n // Counter update\n // ---------------------------------------------------------------------------\n\n _bindContentEvents() {\n const editable = this.context.layoutInfo.editable;\n const updateDebounced = debounce(() => this.update(), 200);\n const d = on(editable, 'input', updateDebounced);\n this._disposers.push(d);\n }\n\n update() {\n if (!this._wordCountEl || !this._charCountEl) return;\n const editable = this.context.layoutInfo.editable;\n const text = editable.innerText || '';\n const words = _countWords(text);\n const chars = text.replace(/\\n/g, '').length;\n const maxWords = this.options.maxWords || 0;\n const maxChars = this.options.maxChars || 0;\n\n const LS = this.context.locale.statusbar;\n this._wordCountEl.textContent = maxWords\n ? LS.wordsLimit(words, maxWords)\n : LS.words(words);\n this._charCountEl.textContent = maxChars\n ? LS.charsLimit(chars, maxChars)\n : LS.chars(chars);\n\n // Apply warning / exceeded styles\n _applyLimitClass(this._wordCountEl, words, maxWords);\n _applyLimitClass(this._charCountEl, chars, maxChars);\n }\n\n /**\n * Returns the current word count of the editor content.\n * @returns {number}\n */\n getWordCount() {\n const editable = this.context.layoutInfo.editable;\n return _countWords(editable.innerText || '');\n }\n\n /**\n * Returns the current character count (excluding newlines) of the editor content.\n * @returns {number}\n */\n getCharCount() {\n const editable = this.context.layoutInfo.editable;\n return ((editable.innerText || '').replace(/\\n/g, '')).length;\n }\n}\n","/**\n * Clipboard.js - Handles paste events to strip unwanted formatting,\n * and paste/drop of image files.\n * Inspired by Summernote's Clipboard module\n */\n\nimport { on } from '../core/dom.js';\nimport { execCommand } from '../editing/Style.js';\nimport { sanitiseHTML } from '../core/sanitise.js';\nimport { isMarkdown, markdownToHTML } from '../core/markdown.js';\n\nexport class Clipboard {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n }\n\n initialize() {\n /** @type {Map<string, string>} Maps blob: URL (in DOM) → data: URL (serialisable) */\n this._blobRegistry = new Map();\n /** @type {boolean} Set to true by Ctrl+Shift+V shortcut to force one-shot plain paste */\n this._forcePlain = false;\n const editable = this.context.layoutInfo.editable;\n this._disposers.push(\n on(editable, 'paste', (e) => this._onPaste(e)),\n on(editable, 'dragover', (e) => this._onDragover(e)),\n on(editable, 'drop', (e) => this._onDrop(e)),\n );\n\n // Watch for removed images so their blob: URLs are revoked immediately,\n // preventing memory leaks during long editing sessions.\n this._mutationObserver = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.removedNodes) {\n this._revokeRemovedBlobs(node);\n }\n }\n });\n this._mutationObserver.observe(editable, { childList: true, subtree: true });\n\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._mutationObserver) {\n this._mutationObserver.disconnect();\n this._mutationObserver = null;\n }\n // Release any remaining object URLs\n if (this._blobRegistry) {\n this._blobRegistry.forEach((_, blobUrl) => URL.revokeObjectURL(blobUrl));\n this._blobRegistry.clear();\n }\n }\n\n /**\n * Revokes blob URLs for any <img> elements removed from the DOM.\n * @param {Node} node\n */\n _revokeRemovedBlobs(node) {\n if (!this._blobRegistry || !this._blobRegistry.size) return;\n const imgs = [];\n if (node.nodeName === 'IMG') {\n imgs.push(node);\n } else if (node.querySelectorAll) {\n imgs.push(...node.querySelectorAll('img'));\n }\n imgs.forEach((img) => {\n const src = img.getAttribute('src') || '';\n if (src.startsWith('blob:') && this._blobRegistry.has(src)) {\n URL.revokeObjectURL(src);\n this._blobRegistry.delete(src);\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Paste handler\n // ---------------------------------------------------------------------------\n\n /**\n * Strips Microsoft Word / Office HTML artefacts from a pasted HTML string.\n * Removes conditional comments, Office namespace elements, MsoXxx classes,\n * mso-* inline style rules, and empty paragraphs left behind by Word.\n * @param {string} html\n * @returns {string}\n */\n _cleanWordHtml(html) {\n return html\n // Conditional comments <!--[if ...]>...<![endif]-->\n .replace(/<!--\\[if[\\s\\S]*?\\[endif\\]-->/gi, '')\n // XML data blobs <xml>...</xml>\n .replace(/<xml[\\s\\S]*?<\\/xml>/gi, '')\n // XML processing instructions <?xml ... ?>\n .replace(/<\\?xml[\\s\\S]*?\\?>/gi, '')\n // Office namespace elements: <o:p>, <w:sDt>, <m:oMath>, <v:shape> …\n .replace(/<\\/?(o|w|m|v|st1):[a-z][^>]*>/gi, '')\n // MsoNormal, MsoBodyText, etc. class attributes\n .replace(/\\s+class=\"Mso[^\"]*\"/gi, '')\n // mso-* properties inside inline style attributes\n .replace(/\\s+style=\"([^\"]*)\"/gi, (_m, style) => {\n const cleaned = style.split(';')\n .map((s) => s.trim())\n .filter((s) => s && !/^mso-/i.test(s) && !/^(tab-stops|margin-[a-z]+-alt)/i.test(s))\n .join('; ');\n return cleaned ? ` style=\"${cleaned}\"` : '';\n })\n // Empty paragraphs Word sprinkles everywhere\n .replace(/<p[^>]*>\\s*( )?\\s*<\\/p>/gi, '');\n }\n\n /**\n * Detects and strips noise from social media sites (Facebook, X/Twitter, LinkedIn, etc.).\n * These React-based pages produce HTML with utility class names like `x1n2onr6` / `r-bcqeeo`,\n * `data-testid`, `data-lexical-*`, etc. We keep the semantic structure but remove all the noise.\n * @param {string} html\n * @returns {string}\n */\n _cleanSocialHtml(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n // Unwrap purely presentational wrapper spans/divs with no semantic meaning.\n // Single-pass reverse traversal: querySelectorAll returns elements in document\n // order, so iterating backwards processes innermost elements first — once a\n // child is unwrapped its parent may become unwrappable in the same pass.\n // This replaces the previous O(n²) while-loop that re-queried the whole tree\n // on every iteration.\n const candidates = Array.from(doc.querySelectorAll('span, div'));\n for (let i = candidates.length - 1; i >= 0; i--) {\n const el = candidates[i];\n if (!el.parentNode) continue; // already detached by an earlier iteration\n // Keep if it contains any semantic child element\n if (el.querySelector('a, strong, em, b, i, ul, ol, li, table, img, blockquote, pre, code, h1, h2, h3, h4, h5, h6')) continue;\n // Unwrap — replace el with its children\n const parent = el.parentNode;\n while (el.firstChild) parent.insertBefore(el.firstChild, el);\n parent.removeChild(el);\n }\n // Strip class and all data-* attributes from every remaining element\n doc.querySelectorAll('*').forEach((el) => {\n el.removeAttribute('class');\n el.removeAttribute('id');\n Array.from(el.attributes)\n .filter((a) => a.name.startsWith('data-') || a.name.startsWith('aria-'))\n .forEach((a) => el.removeAttribute(a.name));\n });\n return doc.body.innerHTML;\n }\n\n /**\n * Strips presentational attributes (class, style, data-*, id) from all elements,\n * keeping only semantic structure and URL attributes.\n * Used when `pasteStripAttributes` option is true.\n * @param {string} html\n * @returns {string}\n */\n _stripAttributes(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n const KEEP_ATTRS = new Set(['href', 'src', 'alt', 'target', 'rel', 'colspan', 'rowspan', 'type']);\n doc.querySelectorAll('*').forEach((el) => {\n Array.from(el.attributes)\n .filter((a) => !KEEP_ATTRS.has(a.name))\n .forEach((a) => el.removeAttribute(a.name));\n });\n return doc.body.innerHTML;\n }\n\n /**\n * Forces the next paste operation to strip all HTML formatting.\n * Called by Editor when Ctrl+Shift+V is pressed.\n * @param {boolean} val\n */\n setForcePlain(val) {\n this._forcePlain = !!val;\n }\n\n _onPaste(event) {\n const clipboardData = event.clipboardData || window.clipboardData;\n if (!clipboardData) return;\n\n // Consume and reset the one-shot plain-paste flag\n const forcePlain = this._forcePlain;\n this._forcePlain = false;\n\n // 1. Image file in clipboard (screenshot, copy-image-from-browser, etc.)\n if (clipboardData.items) {\n const imageItems = Array.from(clipboardData.items).filter(\n (item) => item.kind === 'file' && item.type.startsWith('image/'),\n );\n if (imageItems.length > 0) {\n event.preventDefault();\n const files = imageItems.map((item) => item.getAsFile()).filter(Boolean);\n this._insertImageFiles(files);\n return;\n }\n }\n\n // Fire onPaste hook so consumers can observe / intercept\n if (typeof this.options.onPaste === 'function') {\n this.options.onPaste({\n text: clipboardData.getData('text/plain') || '',\n html: clipboardData.types.includes('text/html') ? clipboardData.getData('text/html') : null,\n });\n }\n\n // 2. Force plain-text only — strip all formatting\n if (forcePlain || this.options.pasteAsPlainText) {\n event.preventDefault();\n const text = clipboardData.getData('text/plain');\n const html = text\n .split(/\\r?\\n/)\n .map((line) => `<p>${this._escapeHTML(line) || '<br>'}</p>`)\n .join('');\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n return;\n }\n\n // 3. Markdown paste — only when no HTML is on the clipboard (pure text source)\n if (this.options.markdownPaste !== false && !clipboardData.types.includes('text/html')) {\n const text = clipboardData.getData('text/plain');\n if (text && isMarkdown(text)) {\n event.preventDefault();\n const html = sanitiseHTML(markdownToHTML(text));\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n return;\n }\n }\n\n // 4. Sanitise HTML on paste when pasteCleanHTML is true (default)\n if (this.options.pasteCleanHTML !== false && clipboardData.types.includes('text/html')) {\n event.preventDefault();\n const raw = clipboardData.getData('text/html');\n // Detect source type and apply appropriate pre-cleaner\n const isWordContent = /<[a-z]+:[a-z]/i.test(raw) || /class=\"Mso/i.test(raw) || /\\bmso-/i.test(raw);\n const isSocialContent = /\\bdata-testid\\b/.test(raw) || /class=\"[^\"]*\\b(?:x[a-z0-9]{6,}|r-[a-z0-9]{3,})\\b/.test(raw);\n let html = raw;\n if (isWordContent) html = this._cleanWordHtml(html);\n else if (isSocialContent) html = this._cleanSocialHtml(html);\n html = sanitiseHTML(html);\n if (this.options.pasteStripAttributes) html = this._stripAttributes(html);\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n return;\n }\n\n // Otherwise let the browser handle paste natively\n }\n\n // ---------------------------------------------------------------------------\n // Drag & drop handlers\n // ---------------------------------------------------------------------------\n\n _onDragover(event) {\n if (!event.dataTransfer) return;\n const types = Array.from(event.dataTransfer.types || []);\n if (types.includes('Files')) {\n event.preventDefault();\n event.dataTransfer.dropEffect = 'copy';\n }\n }\n\n _onDrop(event) {\n const dt = event.dataTransfer;\n if (!dt || !dt.files || dt.files.length === 0) return;\n\n const imageFiles = Array.from(dt.files).filter((f) => f.type.startsWith('image/'));\n if (imageFiles.length === 0) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n // Place the caret at the drop coordinates before inserting\n this._placeCaretAtPoint(event.clientX, event.clientY);\n this._insertImageFiles(imageFiles);\n }\n\n // ---------------------------------------------------------------------------\n // Image file processing — shared by paste and drop\n // ---------------------------------------------------------------------------\n\n /**\n * Inserts one or more image Files into the editor.\n * Delegates to `options.onImageUpload` when provided; otherwise compresses\n * and embeds as base64.\n * @param {File[]} files\n */\n _insertImageFiles(files) {\n if (!files || files.length === 0) return;\n\n if (typeof this.options.onImageUpload === 'function') {\n this.options.onImageUpload(files);\n return;\n }\n\n // C2: Reject image formats that browsers cannot decode/display.\n const UNSUPPORTED = ['image/tiff', 'image/x-tiff', 'image/bmp', 'image/x-bmp', 'image/x-ms-bmp'];\n const maxBytes = (this.options.maxImageSize || 5) * 1024 * 1024;\n files.forEach((file) => {\n if (!file || !file.type.startsWith('image/')) return;\n if (UNSUPPORTED.includes(file.type)) {\n const message = `Image format \"${file.type}\" is not supported for display in web browsers. Please convert to PNG, JPEG, or WebP first.`;\n this.context.triggerEvent('imageError', { file, message });\n console.warn('[AutumnNote]', message);\n return;\n }\n if (file.size > maxBytes) {\n const message = `Image \"${file.name}\" exceeds the ${this.options.maxImageSize || 5} MB size limit.`;\n this.context.triggerEvent('imageError', { file, message });\n console.warn(`[AutumnNote] ${message}`);\n return;\n }\n\n const alt = file.name.replace(/\\.[^.]+$/, '');\n this._compressImage(file).then((dataUrl) => {\n // Keep the large data URL in a JS Map; insert a lightweight blob: URL\n // into the DOM so editable.innerHTML never contains the big base64 string.\n const blob = this._dataUrlToBlob(dataUrl);\n const blobUrl = URL.createObjectURL(blob);\n this._blobRegistry.set(blobUrl, dataUrl);\n this.context.invoke('editor.insertImage', blobUrl, alt);\n }).catch((err) => {\n const message = `Image \"${file.name}\" could not be processed.`;\n this.context.triggerEvent('imageError', { file, message, error: err });\n console.warn('[AutumnNote]', message, err);\n });\n });\n }\n\n /**\n * Replaces any blob: URLs created by this module with their original data URLs.\n * Called by Editor.getHTML() so the returned HTML is fully self-contained.\n * @param {string} html\n * @returns {string}\n */\n resolveImages(html) {\n if (!this._blobRegistry || !this._blobRegistry.size) return html;\n return html.replace(/blob:[^\"'> \\t\\n\\r]*/g, (url) => this._blobRegistry.get(url) || url);\n }\n\n /**\n * Converts a data URL to a Blob (no FileReader — synchronous).\n * @param {string} dataUrl\n * @returns {Blob}\n */\n _dataUrlToBlob(dataUrl) {\n const [header, b64] = dataUrl.split(',');\n const mime = header.match(/:(.*?);/)[1];\n const binary = atob(b64);\n const arr = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) arr[i] = binary.charCodeAt(i);\n return new Blob([arr], { type: mime });\n }\n\n /**\n * Compresses an image File using a Canvas.\n * - Resizes so the longest edge is at most MAX_DIM pixels.\n * - Encodes as WebP (if supported) or JPEG at quality 0.85.\n * Falls back to plain FileReader if canvas is unavailable.\n * @param {File} file\n * @returns {Promise<string>} data URL\n */\n _compressImage(file) {\n const MAX_DIM = 1920;\n const QUALITY = 0.85;\n\n return new Promise((resolve) => {\n const objectUrl = URL.createObjectURL(file);\n const img = new Image();\n\n img.onload = () => {\n URL.revokeObjectURL(objectUrl);\n\n let { width, height } = img;\n if (width > MAX_DIM || height > MAX_DIM) {\n if (width >= height) {\n height = Math.round((height * MAX_DIM) / width);\n width = MAX_DIM;\n } else {\n width = Math.round((width * MAX_DIM) / height);\n height = MAX_DIM;\n }\n }\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n // Canvas context unavailable (e.g. device memory limit) — fall back to\n // embedding the original file without compression.\n const reader = new FileReader();\n reader.onload = (e) => resolve(/** @type {string} */ (e.target.result));\n reader.readAsDataURL(file);\n return;\n }\n ctx.drawImage(img, 0, 0, width, height);\n\n // Prefer WebP for better compression; fall back to JPEG\n const webp = canvas.toDataURL('image/webp', QUALITY);\n resolve(webp.startsWith('data:image/webp') ? webp : canvas.toDataURL('image/jpeg', QUALITY));\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(objectUrl);\n // Fallback: embed original without compression\n const reader = new FileReader();\n reader.onload = (e) => resolve(/** @type {string} */ (e.target.result));\n reader.readAsDataURL(file);\n };\n\n img.src = objectUrl;\n });\n }\n\n /**\n * Positions the caret at the given viewport coordinates.\n * Supports both Chrome (caretRangeFromPoint) and Firefox (caretPositionFromPoint).\n * @param {number} x\n * @param {number} y\n */\n _placeCaretAtPoint(x, y) {\n let range;\n if (document.caretRangeFromPoint) {\n range = document.caretRangeFromPoint(x, y);\n } else if (document.caretPositionFromPoint) {\n const pos = document.caretPositionFromPoint(x, y);\n if (pos) {\n range = document.createRange();\n range.setStart(pos.offsetNode, pos.offset);\n range.collapse(true);\n }\n }\n if (!range) return;\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Escapes HTML special characters.\n * @param {string} str\n * @returns {string}\n */\n _escapeHTML(str) {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n }\n}\n","/**\n * Placeholder.js - Shows placeholder text when the editor is empty\n * Inspired by Summernote's Placeholder module\n */\n\nimport { on } from '../core/dom.js';\n\nexport class Placeholder {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n }\n\n initialize() {\n const editable = this.context.layoutInfo.editable;\n const placeholder = this.options.placeholder || '';\n if (placeholder) {\n editable.dataset.placeholder = placeholder;\n }\n\n const update = () => this._update();\n const d1 = on(editable, 'input', update);\n const d2 = on(editable, 'focus', update);\n const d3 = on(editable, 'blur', update);\n this._disposers.push(d1, d2, d3);\n this._update();\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n }\n\n _update() {\n const editable = this.context.layoutInfo.editable;\n const isFocused = document.activeElement === editable;\n // Strip ZWS (\\u200B) cursor anchors used by checklist/icon insertion in\n // addition to regular whitespace before deciding if the editor is empty.\n // Without this, a freshly-created checklist item or icon leaves a ZWS in\n // the DOM that causes the placeholder to overlap real content (A-1).\n const hasText = editable.textContent.replace(/\\u200B/g, '').trim().length > 0;\n const isEmpty = !hasText &&\n !editable.querySelector('img, table, hr, .an-video-wrapper');\n editable.classList.toggle('an-placeholder', isEmpty && !isFocused);\n }\n}\n","/**\n * Codeview.js - HTML source code view / WYSIWYG toggle\n * Inspired by Summernote's Codeview module\n */\n\nimport { createElement } from '../core/dom.js';\nimport { sanitiseHTML } from '../core/sanitise.js';\n\nexport class Codeview {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._active = false;\n /** @type {HTMLTextAreaElement|null} */\n this._textarea = null;\n this._disposers = [];\n }\n\n initialize() {\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._textarea && this._textarea.parentNode) {\n this._textarea.parentNode.removeChild(this._textarea);\n }\n this._textarea = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n toggle() {\n if (this._active) {\n this.deactivate();\n } else {\n this.activate();\n }\n }\n\n isActive() {\n return this._active;\n }\n\n activate() {\n if (this._active) return;\n const { editable } = this.context.layoutInfo;\n const html = editable.innerHTML;\n\n this._textarea = createElement('textarea', {\n class: 'an-codeview',\n spellcheck: 'false',\n autocomplete: 'off',\n autocorrect: 'off',\n autocapitalize: 'off',\n });\n this._textarea.value = this._prettyPrint(html);\n\n editable.style.display = 'none';\n editable.parentNode.insertBefore(this._textarea, editable.nextSibling);\n\n this._active = true;\n this.context.invoke('toolbar.refresh');\n }\n\n deactivate() {\n if (!this._active || !this._textarea) return;\n const { editable } = this.context.layoutInfo;\n // Sanitise the HTML typed in the textarea before applying (allow iframes for video embeds)\n editable.innerHTML = sanitiseHTML(this._textarea.value, { allowIframes: true });\n this._textarea.parentNode.removeChild(this._textarea);\n this._textarea = null;\n editable.style.display = '';\n this._active = false;\n this.context.invoke('toolbar.refresh');\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Very simple HTML pretty-printer (indent nested tags).\n * Inline elements (a, span, strong, em, etc.) are kept on one line to\n * avoid injecting whitespace that would change rendered text.\n * @param {string} html\n * @returns {string}\n */\n _prettyPrint(html) {\n // Tags whose content must NOT be split with newlines (breaks text rendering)\n const INLINE_RE = /^<(a|abbr|b|bdo|br|button|cite|code|dfn|em|i|img|input|kbd|label|output|q|samp|select|small|span|strong|sub|sup|textarea|time|tt|u|var)([\\s>/])/i;\n let indent = 0;\n return html\n .replace(/>\\s*</g, (match, offset, str) => {\n // Check what comes after the '>' — if it starts an inline tag, keep on same line\n const remaining = str.slice(offset + 1);\n if (INLINE_RE.test(remaining.trimStart())) return '><';\n return '>\\n<';\n })\n .split('\\n')\n .map((line) => {\n const stripped = line.trim();\n if (!stripped) return '';\n if (/^<\\//.test(stripped)) indent = Math.max(0, indent - 1);\n const out = ' '.repeat(indent) + stripped;\n if (\n /^<[^/!][^>]*[^/]>/.test(stripped) &&\n !INLINE_RE.test(stripped) &&\n !/^<(br|hr|img|input|link|meta)/.test(stripped)\n ) {\n indent++;\n }\n return out;\n })\n .filter(Boolean)\n .join('\\n');\n }\n\n}\n\n","/**\n * Fullscreen.js - Toggles the editor in/out of fullscreen mode\n * Inspired by Summernote's Fullscreen module\n */\n\nimport { on } from '../core/dom.js';\nimport { key, isKey } from '../core/key.js';\n\nexport class Fullscreen {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this._active = false;\n this._disposers = [];\n /** @type {string} cached editable height before fullscreen */\n this._prevHeight = '';\n }\n\n initialize() {\n // Press Escape to exit fullscreen\n const d = on(document, 'keydown', (event) => {\n if (this._active && isKey(event, key.ESCAPE)) {\n this.deactivate();\n }\n });\n this._disposers.push(d);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._active) this.deactivate();\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n toggle() {\n if (this._active) {\n this.deactivate();\n } else {\n this.activate();\n }\n }\n\n isActive() {\n return this._active;\n }\n\n activate() {\n if (this._active) return;\n const container = this.context.layoutInfo.container;\n // Save the container's explicit height (set by the resize handle) so it\n // can be restored when exiting fullscreen.\n this._prevHeight = container.style.height;\n\n container.classList.add('an-fullscreen');\n // Clear any resize-imposed height so the fullscreen CSS (inset:0) takes over.\n container.style.height = '';\n document.body.style.overflow = 'hidden';\n this._active = true;\n this.context.invoke('toolbar.refresh');\n }\n\n deactivate() {\n if (!this._active) return;\n const container = this.context.layoutInfo.container;\n\n container.classList.remove('an-fullscreen');\n // Restore whatever explicit height the user had set via the resize handle.\n container.style.height = this._prevHeight;\n document.body.style.overflow = '';\n this._active = false;\n this.context.invoke('toolbar.refresh');\n }\n}\n","/**\n * LinkDialog.js - Dialog for inserting / editing hyperlinks\n * Inspired by Summernote's LinkDialog — rewritten without jQuery\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\nexport class LinkDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the link dialog.\n * Pre-fills with the currently selected link if present.\n */\n show() {\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._prefill();\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.linkDialog;\n const overlay = createElement('div', { class: 'an-dialog-overlay', role: 'dialog', 'aria-modal': 'true', 'aria-label': L.ariaLabel });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n\n // URL field\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.url;\n const urlInput = createElement('input', {\n type: 'url',\n class: 'an-input',\n placeholder: L.urlPlaceholder,\n id: 'an-link-url',\n name: 'url',\n autocomplete: 'off',\n });\n this._urlInput = urlInput;\n\n // Text field\n const textLabel = createElement('label', { class: 'an-label' });\n textLabel.textContent = L.displayText;\n const textInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.textPlaceholder,\n id: 'an-link-text',\n name: 'linkText',\n autocomplete: 'off',\n });\n this._textInput = textInput;\n\n // Open in new tab\n const tabLabel = createElement('label', { class: 'an-label an-label-inline' });\n const tabCheckbox = createElement('input', {\n type: 'checkbox',\n id: 'an-link-newtab',\n name: 'openInNewTab',\n });\n this._tabCheckbox = tabCheckbox;\n tabLabel.appendChild(tabCheckbox);\n tabLabel.appendChild(document.createTextNode(' ' + L.openInNewTab));\n\n // Buttons\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n box.append(title, urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);\n overlay.appendChild(box);\n\n // Events\n const d1 = on(insertBtn, 'click', () => this._onInsert());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(urlInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(textInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d1, d2, d3, d4, d5);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _prefill() {\n // Try to find currently selected anchor\n const sel = window.getSelection();\n let anchor = null;\n if (sel && sel.rangeCount > 0) {\n let node = sel.getRangeAt(0).startContainer;\n while (node) {\n if (node.nodeName === 'A') { anchor = node; break; }\n node = node.parentNode;\n }\n }\n if (anchor) {\n this._urlInput.value = anchor.getAttribute('href') || '';\n this._textInput.value = anchor.textContent || '';\n this._tabCheckbox.checked = anchor.getAttribute('target') === '_blank';\n } else {\n this._urlInput.value = '';\n this._textInput.value = sel ? sel.toString() : '';\n this._tabCheckbox.checked = false;\n }\n }\n\n _onInsert() {\n let url = this._urlInput.value.trim();\n const text = this._textInput.value.trim();\n const newTab = this._tabCheckbox.checked;\n\n if (!url) {\n this._urlInput.focus();\n return;\n }\n\n // Auto-prefix with https:// if no protocol is present\n if (!/^[a-zA-Z][a-zA-Z\\d+\\-.]*:/.test(url)) {\n url = 'https://' + url;\n }\n\n // Block unsafe protocols\n try {\n const parsed = new URL(url);\n if (/^javascript:/i.test(parsed.protocol) || /^vbscript:/i.test(parsed.protocol) || /^data:/i.test(parsed.protocol)) {\n this._urlInput.focus();\n return;\n }\n } catch {\n // URL constructor failed — not a valid URL\n this._urlInput.focus();\n return;\n }\n\n // Restore selection then insert\n if (this._savedRange) {\n this._savedRange.select();\n }\n\n this.context.invoke('editor.insertLink', url, text, newTab);\n this._close();\n }\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._urlInput && this._urlInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n}\n","/**\n * ImageDialog.js - Dialog for inserting images (by URL or file upload)\n * Inspired by Summernote's ImageDialog — rewritten without jQuery\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\nexport class ImageDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._urlInput.value = '';\n this._altInput.value = '';\n if (this._fileInput) this._fileInput.value = '';\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.imageDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n\n // URL tab\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.imageUrl;\n const urlInput = createElement('input', {\n type: 'url',\n class: 'an-input',\n placeholder: L.urlPlaceholder,\n autocomplete: 'off',\n });\n this._urlInput = urlInput;\n\n // Alt text\n const altLabel = createElement('label', { class: 'an-label' });\n altLabel.textContent = L.altText;\n const altInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.altPlaceholder,\n autocomplete: 'off',\n });\n this._altInput = altInput;\n\n box.append(title, urlLabel, urlInput, altLabel, altInput);\n\n // Alignment\n const alignLabel = createElement('label', { class: 'an-label' });\n alignLabel.textContent = L.alignment;\n const alignRow = createElement('div', { class: 'an-align-row' });\n const alignOptions = [\n { value: '', label: L.alignNone },\n { value: 'left', label: L.alignLeft },\n { value: 'center', label: L.alignCenter },\n { value: 'right', label: L.alignRight },\n ];\n alignOptions.forEach(({ value, label }) => {\n const radioId = `an-align-${value || 'none'}`;\n const radio = createElement('input', { type: 'radio', name: 'an-img-align', id: radioId, value });\n if (value === '') radio.checked = true;\n const lbl = createElement('label', { for: radioId, class: 'an-align-label' });\n lbl.textContent = label;\n alignRow.append(radio, lbl);\n });\n this._alignRow = alignRow;\n box.append(alignLabel, alignRow);\n if (this.options.allowImageUpload !== false) {\n const fileLabel = createElement('label', { class: 'an-label' });\n fileLabel.textContent = L.uploadLabel;\n const fileInput = createElement('input', {\n type: 'file',\n class: 'an-input',\n accept: 'image/jpeg,image/png,image/gif,image/webp,image/svg+xml,image/avif',\n });\n this._fileInput = fileInput;\n // Hint line shown below the file input for format errors\n const fileHint = createElement('p', { class: 'an-dialog-hint' });\n this._fileHint = fileHint;\n const d = on(fileInput, 'change', () => this._onFileChange());\n this._disposers.push(d);\n box.append(fileLabel, fileInput, fileHint);\n }\n\n // Buttons\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n box.append(btnRow);\n overlay.appendChild(box);\n\n const d1 = on(insertBtn, 'click', () => this._onInsert());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(urlInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(altInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d1, d2, d3, d4, d5);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _onFileChange() {\n const file = this._fileInput && this._fileInput.files && this._fileInput.files[0];\n if (!file || !file.type.startsWith('image/')) return;\n\n // C2: Only allow web-displayable formats. TIFF, BMP, RAW and similar\n // formats are not rendered by browsers — reject them with a clear message.\n const SUPPORTED = new Set([\n 'image/jpeg', 'image/png', 'image/gif',\n 'image/webp', 'image/svg+xml', 'image/avif',\n ]);\n if (!SUPPORTED.has(file.type)) {\n const message = this.context.locale.errors.imageFormat(file.type);\n if (this._fileHint) this._fileHint.textContent = message;\n this.context.triggerEvent('imageError', { file, message });\n this._fileInput.value = '';\n return;\n }\n if (this._fileHint) this._fileHint.textContent = '';\n\n // Validate file size (max 5 MB by default)\n const maxSize = (this.options.maxImageSize || 5) * 1024 * 1024;\n if (file.size > maxSize) {\n const message = this.context.locale.errors.imageSize(this.options.maxImageSize || 5);\n if (this._fileHint) this._fileHint.textContent = message;\n console.warn('[AutumnNote] ImageDialog:', message);\n this.context.triggerEvent('imageError', { file, message });\n this._fileInput.value = '';\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e) => {\n this._urlInput.value = /** @type {string} */ (e.target.result);\n };\n reader.readAsDataURL(file);\n }\n\n _onInsert() {\n const src = this._urlInput.value.trim();\n const alt = this._altInput.value.trim();\n const alignRadio = this._alignRow && this._alignRow.querySelector('input[name=\"an-img-align\"]:checked');\n const align = alignRadio ? alignRadio.value : '';\n\n if (!src) {\n this._urlInput.focus();\n return;\n }\n\n if (this._savedRange) {\n this._savedRange.select();\n }\n\n this.context.invoke('editor.insertImage', src, alt, align);\n this._close();\n }\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._urlInput && this._urlInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n}\n","/**\n * VideoDialog.js - Dialog for inserting videos (YouTube, Vimeo, or direct file)\n * Supports:\n * • YouTube watch URLs → <iframe> embed\n * • YouTube short URLs → <iframe> embed\n * • Vimeo URLs → <iframe> embed\n * • Direct video URLs → <video> element (.mp4 / .webm / .ogg)\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\nexport class VideoDialog {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._urlInput.value = '';\n this._widthInput.value = '560';\n this._hintEl.textContent = '';\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.videoDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n\n // URL input\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.videoUrl;\n const urlInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'url',\n class: 'an-input',\n placeholder: L.urlPlaceholder,\n autocomplete: 'off',\n }));\n this._urlInput = urlInput;\n\n // Hint (detected source)\n const hintEl = createElement('p', { class: 'an-dialog-hint' });\n this._hintEl = hintEl;\n\n // Width\n const widthLabel = createElement('label', { class: 'an-label' });\n widthLabel.textContent = L.widthLabel;\n const widthInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'number',\n class: 'an-input',\n placeholder: '560',\n min: '80',\n max: '1920',\n value: '560',\n }));\n this._widthInput = widthInput;\n\n // Buttons\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n box.append(title, urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);\n overlay.appendChild(box);\n\n // Live URL hint\n const d0 = on(urlInput, 'input', () => {\n const info = this._parseVideoUrl(urlInput.value.trim());\n hintEl.textContent = info ? this.context.locale.videoDialog.detected(info.type) : (urlInput.value ? this.context.locale.videoDialog.unknownFormat : '');\n });\n\n const d1 = on(insertBtn, 'click', () => this._onInsert());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d0, d1, d2, d3, d4);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _onInsert() {\n const rawUrl = this._urlInput.value.trim();\n const width = Math.max(80, parseInt(this._widthInput.value, 10) || 560);\n\n if (!rawUrl) {\n this._urlInput.focus();\n return;\n }\n\n const html = this._buildEmbedHtml(rawUrl, width);\n if (!html) {\n this._hintEl.textContent = this.context.locale.videoDialog.invalidUrl;\n this._urlInput.focus();\n return;\n }\n\n if (this._savedRange) this._savedRange.select();\n this.context.invoke('editor.insertVideo', html);\n this._close();\n }\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._urlInput && this._urlInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // URL parsing & HTML building\n // ---------------------------------------------------------------------------\n\n /**\n * Parses a video URL and returns { type, embedUrl } or null.\n * @param {string} url\n * @returns {{ type: string, embedUrl: string }|null}\n */\n _parseVideoUrl(url) {\n if (!url) return null;\n\n // Validate — block javascript: and other dangerous protocols\n try {\n const parsed = new URL(url);\n if (/^javascript:/i.test(parsed.protocol) || /^vbscript:/i.test(parsed.protocol)) return null;\n } catch { return null; }\n\n // YouTube watch: https://www.youtube.com/watch?v=ID\n const ytWatch = url.match(/(?:youtube\\.com\\/watch\\?(?:.*&)?v=|youtube\\.com\\/embed\\/)([a-zA-Z0-9_-]{11})/);\n if (ytWatch) return { type: 'YouTube', embedUrl: `https://www.youtube.com/embed/${ytWatch[1]}` };\n\n // YouTube short: https://youtu.be/ID\n const ytShort = url.match(/youtu\\.be\\/([a-zA-Z0-9_-]{11})/);\n if (ytShort) return { type: 'YouTube', embedUrl: `https://www.youtube.com/embed/${ytShort[1]}` };\n\n // YouTube Shorts: https://www.youtube.com/shorts/ID\n const ytShorts = url.match(/youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]{11})/);\n if (ytShorts) return { type: 'YouTube Shorts', embedUrl: `https://www.youtube.com/embed/${ytShorts[1]}` };\n\n // Vimeo: https://vimeo.com/ID\n const vimeo = url.match(/vimeo\\.com\\/(\\d+)/);\n if (vimeo) return { type: 'Vimeo', embedUrl: `https://player.vimeo.com/video/${vimeo[1]}` };\n\n // Direct video file\n if (/\\.(mp4|webm|ogg|ogv|mov)(#.*|\\?.*)?$/i.test(url)) {\n return { type: 'Direct video', embedUrl: url };\n }\n\n return null;\n }\n\n /**\n * Builds the HTML string to insert.\n * @param {string} url\n * @param {number} width\n * @returns {string|null}\n */\n _buildEmbedHtml(url, width) {\n const info = this._parseVideoUrl(url);\n const height = Math.round(width * 9 / 16); // 16:9\n\n if (info && (info.type === 'YouTube' || info.type === 'YouTube Shorts' || info.type === 'Vimeo')) {\n const iframeTitle = `${info.type} video player`;\n return (\n `<div class=\"an-video-wrapper\" style=\"position:relative;display:block;width:${width}px;max-width:100%\">` +\n `<iframe src=\"${info.embedUrl}\" width=\"${width}\" height=\"${height}\" ` +\n `title=\"${iframeTitle}\" ` +\n `frameborder=\"0\" allowfullscreen ` +\n `allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" ` +\n `style=\"display:block;max-width:100%\"></iframe>` +\n `<div class=\"an-video-shield\"></div>` +\n `</div>`\n );\n }\n\n if (info && info.type === 'Direct video') {\n const src = info.embedUrl.replace(/\"/g, '%22');\n return (\n `<div class=\"an-video-wrapper\" style=\"position:relative;display:block;width:${width}px;max-width:100%\">` +\n `<video src=\"${src}\" width=\"${width}\" height=\"${height}\" controls ` +\n `style=\"display:block;max-width:100%\"></video>` +\n `<div class=\"an-video-shield\"></div>` +\n `</div>`\n );\n }\n\n // Unknown URL — let the user try as a direct video\n const safeSrc = (() => {\n try {\n const p = new URL(url);\n if (/^javascript:/i.test(p.protocol) || /^vbscript:/i.test(p.protocol)) return null;\n return url;\n } catch { return null; }\n })();\n if (!safeSrc) return null;\n\n const escapedSrc = safeSrc.replace(/\"/g, '%22');\n return (\n `<div class=\"an-video-wrapper\" style=\"position:relative;display:block;width:${width}px;max-width:100%\">` +\n `<video src=\"${escapedSrc}\" width=\"${width}\" height=\"${height}\" controls ` +\n `style=\"display:block;max-width:100%\"></video>` +\n `<div class=\"an-video-shield\"></div>` +\n `</div>`\n );\n }\n}\n","// ImageResizer.js - Interactive resize handles for selected images in the editor\nimport { on } from '../core/dom.js';\n\n/**\n * Eight handle positions. 'pos' is used as CSS class suffix and\n * to determine which axis/direction is being dragged.\n *\n * Pos length 2 → corner handle → maintain aspect ratio.\n * Pos length 1 → edge handle → single-axis resize.\n */\nconst HANDLE_DEFS = [\n { pos: 'nw', cursor: 'nw-resize' },\n { pos: 'n', cursor: 'n-resize' },\n { pos: 'ne', cursor: 'ne-resize' },\n { pos: 'e', cursor: 'e-resize' },\n { pos: 'se', cursor: 'se-resize' },\n { pos: 's', cursor: 's-resize' },\n { pos: 'sw', cursor: 'sw-resize' },\n { pos: 'w', cursor: 'w-resize' },\n];\n\nexport class ImageResizer {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLImageElement|null} */\n this._activeImg = null;\n this._overlay = null;\n this._disposers = [];\n this._positionRaf = null;\n }\n\n initialize() {\n this._overlay = this._buildOverlay();\n const container = this.context.layoutInfo.editable.closest('.an-container') || document.body;\n container.appendChild(this._overlay);\n this._container = container;\n\n const editable = this.context.layoutInfo.editable;\n\n // Debounce window resize — _updateOverlayPosition already has rAF gating but\n // every call cancels + re-schedules it; a debounce reduces that churn.\n let _resizeDebounce = null;\n const onWindowResize = () => {\n clearTimeout(_resizeDebounce);\n _resizeDebounce = setTimeout(() => this._updateOverlayPosition(), 100);\n };\n\n this._disposers.push(\n on(editable, 'click', (e) => this._onEditorClick(e)),\n // Also select on right-click so the highlight shows before the context menu\n on(editable, 'contextmenu', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const img = e.target.closest('img');\n if (img) this._select(img);\n }),\n on(document, 'click', (e) => this._onDocClick(e)),\n on(window, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n on(window, 'resize', onWindowResize, { passive: true }),\n on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n );\n\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dragDisposers) {\n this._dragDisposers.forEach((d) => d());\n this._dragDisposers = null;\n }\n if (this._positionRaf) {\n cancelAnimationFrame(this._positionRaf);\n this._positionRaf = null;\n }\n this._deselect();\n if (this._overlay && this._overlay.parentNode) {\n this._overlay.parentNode.removeChild(this._overlay);\n }\n this._overlay = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLImageElement|null} */\n getActiveImage() {\n return this._activeImg;\n }\n\n /** Re-sync overlay position (call after external size changes). */\n updateOverlay() {\n this._updateOverlayPosition();\n }\n\n /** Programmatically clear the current image selection. */\n deselect() {\n this._deselect();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n _buildOverlay() {\n const overlay = document.createElement('div');\n overlay.className = 'an-image-resizer';\n overlay.style.display = 'none';\n\n HANDLE_DEFS.forEach(({ pos }) => {\n const h = document.createElement('div');\n h.className = `an-resize-handle an-resize-${pos}`;\n h.dataset.handle = pos;\n // Attach handle listeners here so they're torn down in destroy() via _disposers\n this._disposers.push(\n on(h, 'mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startResize(e, pos);\n }),\n );\n overlay.appendChild(h);\n });\n\n return overlay;\n }\n\n _onEditorClick(e) {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const img = e.target.closest('img');\n if (img) {\n // Prevent browser from deselecting the current text selection / opening native resize\n e.preventDefault();\n this._select(img);\n }\n }\n\n _onDocClick(e) {\n if (!this._activeImg) return;\n if (e.target === this._activeImg) return;\n if (this._overlay && this._overlay.contains(e.target)) return;\n // Don't deselect while interacting with the context menu\n if (e.target.closest('.an-contextmenu')) return;\n this._deselect();\n }\n\n _select(img) {\n if (this._activeImg && this._activeImg !== img) {\n this._activeImg.classList.remove('an-image-selected');\n }\n this._activeImg = img;\n img.classList.add('an-image-selected');\n this._updateOverlayPosition();\n this._overlay.style.display = 'block';\n }\n\n _deselect() {\n if (this._activeImg) {\n this._activeImg.classList.remove('an-image-selected');\n this._activeImg = null;\n }\n if (this._overlay) this._overlay.style.display = 'none';\n }\n\n _updateOverlayPosition() {\n if (this._positionRaf) cancelAnimationFrame(this._positionRaf);\n this._positionRaf = requestAnimationFrame(() => {\n this._positionRaf = null;\n this._updateOverlayPositionNow();\n });\n }\n\n _updateOverlayPositionNow() {\n if (!this._activeImg || !this._overlay) return;\n const offsetParent = this._overlay.offsetParent || this._container;\n const containerRect = offsetParent.getBoundingClientRect();\n const rect = this._activeImg.getBoundingClientRect();\n const left = rect.left - containerRect.left + offsetParent.scrollLeft;\n const top = rect.top - containerRect.top + offsetParent.scrollTop;\n this._overlay.style.left = `${left}px`;\n this._overlay.style.top = `${top}px`;\n this._overlay.style.width = `${rect.width}px`;\n this._overlay.style.height = `${rect.height}px`;\n }\n\n _startResize(e, pos) {\n const img = this._activeImg;\n if (!img) return;\n\n const startX = e.clientX;\n const startY = e.clientY;\n const startW = img.offsetWidth || img.naturalWidth || 100;\n const startH = img.offsetHeight || img.naturalHeight || 100;\n const aspectRatio = startW / (startH || 1);\n const isCorner = pos.length === 2; // 'nw','ne','se','sw'\n\n const editable = this.context.layoutInfo.editable;\n let _raf = null; // rAF handle — ensures at most one write per paint frame\n\n const onMove = (me) => {\n if (_raf !== null) return; // frame already pending, discard this event\n const clientX = me.clientX;\n const clientY = me.clientY;\n _raf = requestAnimationFrame(() => {\n _raf = null;\n const dx = clientX - startX;\n const dy = clientY - startY;\n const maxW = editable.clientWidth || Infinity;\n let newW = startW;\n let newH = startH;\n\n if (pos.includes('e')) newW = Math.max(20, startW + dx);\n if (pos.includes('w')) newW = Math.max(20, startW - dx);\n if (pos.includes('s')) newH = Math.max(20, startH + dy);\n if (pos.includes('n')) newH = Math.max(20, startH - dy);\n\n newW = Math.min(newW, maxW);\n\n if (isCorner) {\n if (Math.abs(dx) >= Math.abs(dy)) {\n newH = Math.max(20, Math.round(newW / aspectRatio));\n } else {\n newW = Math.min(Math.max(20, Math.round(newH * aspectRatio)), maxW);\n newH = Math.max(20, Math.round(newW / aspectRatio));\n }\n }\n\n img.style.width = `${newW}px`;\n img.style.height = `${newH}px`;\n this._updateOverlayPosition();\n });\n };\n\n const onUp = () => {\n if (_raf !== null) { cancelAnimationFrame(_raf); _raf = null; }\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this._dragDisposers = null;\n this.context.invoke('editor.afterCommand');\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n // Track these so destroy() can clean them up if called during an active drag\n this._dragDisposers = [\n () => document.removeEventListener('mousemove', onMove),\n () => document.removeEventListener('mouseup', onUp),\n ];\n }\n}\n","// VideoResizer.js - Interactive resize handles for selected videos in the editor\n// Targets .an-video-wrapper divs (containing <iframe> or <video>)\nimport { on } from '../core/dom.js';\n\nconst HANDLE_DEFS = [\n { pos: 'nw', cursor: 'nw-resize' },\n { pos: 'n', cursor: 'n-resize' },\n { pos: 'ne', cursor: 'ne-resize' },\n { pos: 'e', cursor: 'e-resize' },\n { pos: 'se', cursor: 'se-resize' },\n { pos: 's', cursor: 's-resize' },\n { pos: 'sw', cursor: 'sw-resize' },\n { pos: 'w', cursor: 'w-resize' },\n];\n\nexport class VideoResizer {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} — the .an-video-wrapper div */\n this._activeWrapper = null;\n this._overlay = null;\n this._disposers = [];\n this._positionRaf = null;\n }\n\n initialize() {\n this._overlay = this._buildOverlay();\n const container = this.context.layoutInfo.editable.closest('.an-container') || document.body;\n container.appendChild(this._overlay);\n this._container = container;\n\n const editable = this.context.layoutInfo.editable;\n\n let _resizeDebounce = null;\n const onWindowResize = () => {\n clearTimeout(_resizeDebounce);\n _resizeDebounce = setTimeout(() => this._updateOverlayPosition(), 100);\n };\n\n this._disposers.push(\n on(editable, 'click', (e) => this._onEditorClick(e)),\n on(editable, 'contextmenu', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const wrapper = this._findWrapper(e.target);\n if (wrapper) this._select(wrapper);\n }),\n on(document, 'click', (e) => this._onDocClick(e)),\n on(window, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n on(window, 'resize', onWindowResize),\n on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n // D1: Prevent native browser drag of video wrappers. Without this, a user\n // can hold-and-drag to produce a \"copy\" that lands outside .an-editable,\n // where the .an-video-shield CSS loses its containing context so the\n // copied video becomes directly playable.\n on(editable, 'dragstart', (e) => {\n if (e.target instanceof Element && e.target.closest('.an-video-wrapper')) {\n e.preventDefault();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dragDisposers) {\n this._dragDisposers.forEach((d) => d());\n this._dragDisposers = null;\n }\n if (this._positionRaf) {\n cancelAnimationFrame(this._positionRaf);\n this._positionRaf = null;\n }\n this._deselect();\n if (this._overlay && this._overlay.parentNode) {\n this._overlay.parentNode.removeChild(this._overlay);\n }\n this._overlay = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLElement|null} */\n getActiveWrapper() {\n return this._activeWrapper;\n }\n\n updateOverlay() {\n this._updateOverlayPosition();\n }\n\n deselect() {\n this._deselect();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n /**\n * Walk up the DOM from `el` to find the nearest .an-video-wrapper,\n * or an iframe/video whose parent is .an-video-wrapper.\n * @param {EventTarget} el\n * @returns {HTMLElement|null}\n */\n _findWrapper(el) {\n if (!el || !(el instanceof Element)) return null;\n // Direct hit on wrapper\n if (el.classList && el.classList.contains('an-video-wrapper')) return el;\n // Child element (iframe, video, or nested)\n const w = el.closest('.an-video-wrapper');\n if (w) return w;\n return null;\n }\n\n _buildOverlay() {\n const overlay = document.createElement('div');\n overlay.className = 'an-video-resizer';\n overlay.style.display = 'none';\n\n HANDLE_DEFS.forEach(({ pos }) => {\n const h = document.createElement('div');\n h.className = `an-resize-handle an-resize-${pos}`;\n h.dataset.handle = pos;\n this._disposers.push(\n on(h, 'mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startResize(e, pos);\n }),\n );\n overlay.appendChild(h);\n });\n\n return overlay;\n }\n\n _onEditorClick(e) {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const wrapper = this._findWrapper(e.target);\n if (wrapper) {\n e.preventDefault();\n this._select(wrapper);\n }\n }\n\n _onDocClick(e) {\n if (!this._activeWrapper) return;\n if (this._activeWrapper.contains(e.target)) return;\n if (this._overlay && this._overlay.contains(e.target)) return;\n if (e.target.closest('.an-contextmenu')) return;\n this._deselect();\n }\n\n _select(wrapper) {\n if (this._activeWrapper && this._activeWrapper !== wrapper) {\n this._activeWrapper.classList.remove('an-video-selected');\n }\n this._activeWrapper = wrapper;\n wrapper.classList.add('an-video-selected');\n this._updateOverlayPosition();\n this._overlay.style.display = 'block';\n }\n\n _deselect() {\n if (this._activeWrapper) {\n this._activeWrapper.classList.remove('an-video-selected');\n this._activeWrapper = null;\n }\n if (this._overlay) this._overlay.style.display = 'none';\n }\n\n _updateOverlayPosition() {\n if (this._positionRaf) cancelAnimationFrame(this._positionRaf);\n this._positionRaf = requestAnimationFrame(() => {\n this._positionRaf = null;\n this._updateOverlayPositionNow();\n });\n }\n\n _updateOverlayPositionNow() {\n if (!this._activeWrapper || !this._overlay) return;\n const offsetParent = this._overlay.offsetParent || this._container;\n const containerRect = offsetParent.getBoundingClientRect();\n const rect = this._activeWrapper.getBoundingClientRect();\n const left = rect.left - containerRect.left + offsetParent.scrollLeft;\n const top = rect.top - containerRect.top + offsetParent.scrollTop;\n this._overlay.style.left = `${left}px`;\n this._overlay.style.top = `${top}px`;\n this._overlay.style.width = `${rect.width}px`;\n this._overlay.style.height = `${rect.height}px`;\n }\n\n _startResize(e, pos) {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n\n const embed = wrapper.querySelector('iframe, video');\n const startX = e.clientX;\n const startY = e.clientY;\n const startW = wrapper.offsetWidth || 560;\n const startH = wrapper.offsetHeight || 315;\n const aspectRatio = startW / (startH || 1);\n const isCorner = pos.length === 2;\n\n const editable = this.context.layoutInfo.editable;\n let _raf = null; // rAF handle — at most one write per paint frame\n\n const onMove = (me) => {\n if (_raf !== null) return;\n const clientX = me.clientX;\n const clientY = me.clientY;\n _raf = requestAnimationFrame(() => {\n _raf = null;\n const dx = clientX - startX;\n const dy = clientY - startY;\n const maxW = editable.clientWidth || Infinity;\n let newW = startW;\n let newH = startH;\n\n if (pos.includes('e')) newW = Math.max(80, startW + dx);\n if (pos.includes('w')) newW = Math.max(80, startW - dx);\n if (pos.includes('s')) newH = Math.max(45, startH + dy);\n if (pos.includes('n')) newH = Math.max(45, startH - dy);\n\n newW = Math.min(newW, maxW);\n\n if (isCorner) {\n if (Math.abs(dx) >= Math.abs(dy)) {\n newH = Math.max(45, Math.round(newW / aspectRatio));\n } else {\n newW = Math.min(Math.max(80, Math.round(newH * aspectRatio)), maxW);\n newH = Math.max(45, Math.round(newW / aspectRatio));\n }\n }\n\n // Resize wrapper and inner embed via CSS only — attribute writes are redundant\n wrapper.style.width = `${newW}px`;\n wrapper.style.height = `${newH}px`;\n if (embed) {\n embed.style.width = `${newW}px`;\n embed.style.height = `${newH}px`;\n }\n this._updateOverlayPosition();\n });\n };\n\n const onUp = () => {\n if (_raf !== null) { cancelAnimationFrame(_raf); _raf = null; }\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this._dragDisposers = null;\n this.context.invoke('editor.afterCommand');\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n // Track these so destroy() can clean them up if called during an active drag\n this._dragDisposers = [\n () => document.removeEventListener('mousemove', onMove),\n () => document.removeEventListener('mouseup', onUp),\n ];\n }\n}\n","// LinkTooltip.js - Hover tooltip for links inside the editor\n// Displays a small action bar with: visit link, edit link, unlink\nimport { createElement, on } from '../core/dom.js';\n\nconst ICONS = {\n open: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/></svg>`,\n edit: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`,\n unlink: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18.84 12.25l1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71\"/><path d=\"M5.17 11.75l-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71\"/><line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"5\"/><line x1=\"2\" y1=\"8\" x2=\"5\" y2=\"8\"/><line x1=\"16\" y1=\"19\" x2=\"16\" y2=\"22\"/><line x1=\"19\" y1=\"16\" x2=\"22\" y2=\"16\"/></svg>`,\n copy: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`,\n};\n\n/** Delay in ms before showing / after hiding to avoid flicker */\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 200;\n\nexport class LinkTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeAnchor = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n // Detect when pointer enters a link\n on(editable, 'mouseover', (e) => {\n const anchor = e.target.closest('a[href]');\n if (anchor && editable.contains(anchor)) {\n this._scheduleShow(anchor);\n }\n }),\n // Detect when pointer leaves the editable area entirely\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.link;\n const el = createElement('div', { class: 'an-link-tooltip', role: 'toolbar', 'aria-label': L.ariaLabel });\n el.style.display = 'none';\n\n // URL preview text (truncated)\n this._urlLabel = createElement('span', { class: 'an-link-tooltip-url' });\n el.appendChild(this._urlLabel);\n\n // Separator\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n // Action buttons\n this._openBtn = this._makeBtn(ICONS.open, L.openLink, () => this._openLink());\n this._copyBtn = this._makeBtn(ICONS.copy, L.copyUrl, () => this._copyLink());\n this._editBtn = this._makeBtn(ICONS.edit, L.editLink, () => this._editLink());\n this._unlinkBtn = this._makeBtn(ICONS.unlink, L.removeLink, () => this._unlink());\n\n el.appendChild(this._openBtn);\n el.appendChild(this._copyBtn);\n el.appendChild(this._editBtn);\n el.appendChild(this._unlinkBtn);\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n _makeBtn(icon, title, handler) {\n const btn = createElement('button', { type: 'button', class: 'an-link-tooltip-btn', title });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => { e.preventDefault(); e.stopPropagation(); handler(); }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide logic\n // ---------------------------------------------------------------------------\n\n _scheduleShow(anchor) {\n if (this._activeAnchor === anchor && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeAnchor = anchor;\n this._show(anchor);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n if (this._hideTimer) return;\n this._hideTimer = setTimeout(() => {\n this._hide();\n }, HIDE_DELAY);\n }\n\n _show(anchor) {\n const isReadOnly = this.context.layoutInfo.container.classList.contains('an-disabled');\n const url = anchor.getAttribute('href') || '';\n this._urlLabel.textContent = this._truncateUrl(url);\n this._urlLabel.title = url;\n // In read-only mode keep only open + copy; hide edit and unlink\n this._editBtn.style.display = isReadOnly ? 'none' : '';\n this._unlinkBtn.style.display = isReadOnly ? 'none' : '';\n this._el.style.display = 'flex';\n this._positionNear(anchor);\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activeAnchor = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(anchor) {\n const rect = anchor.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 260;\n const tipH = this._el.offsetHeight || 34;\n const margin = 6;\n\n // Prefer below the link; if no room, put above\n let top = rect.bottom + margin;\n let left = rect.left;\n\n if (top + tipH > window.innerHeight - margin) {\n top = rect.top - tipH - margin;\n }\n if (left + tipW > window.innerWidth - margin) {\n left = window.innerWidth - tipW - margin;\n }\n if (left < margin) left = margin;\n\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n _truncateUrl(url) {\n try {\n const u = new URL(url);\n const display = u.host + (u.pathname !== '/' ? u.pathname : '');\n return display.length > 48 ? display.slice(0, 48) + '…' : display;\n } catch {\n return url.length > 48 ? url.slice(0, 48) + '…' : url;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _openLink() {\n const url = this._activeAnchor && this._activeAnchor.getAttribute('href');\n if (url) window.open(url, '_blank', 'noopener,noreferrer');\n this._hide();\n }\n\n _copyLink() {\n const url = this._activeAnchor && this._activeAnchor.getAttribute('href');\n if (url) {\n navigator.clipboard.writeText(url).catch(() => {\n // Fallback for environments where clipboard API is unavailable\n const ta = document.createElement('textarea');\n ta.value = url;\n ta.style.position = 'fixed';\n ta.style.opacity = '0';\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n });\n }\n // Brief visual feedback \n if (this._copyBtn) {\n this._copyBtn.classList.add('an-link-tooltip-btn--copied');\n setTimeout(() => this._copyBtn && this._copyBtn.classList.remove('an-link-tooltip-btn--copied'), 1000);\n }\n }\n\n _editLink() {\n const anchor = this._activeAnchor;\n if (!anchor) return;\n this._hide();\n\n // Place cursor inside the anchor, then open the link dialog (which pre-fills from selection)\n const sel = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(anchor);\n sel.removeAllRanges();\n sel.addRange(range);\n\n this.context.invoke('linkDialog.show');\n }\n\n _unlink() {\n const anchor = this._activeAnchor;\n if (!anchor) return;\n this._hide();\n\n // Select the anchor text, then remove the link\n const sel = window.getSelection();\n const range = document.createRange();\n range.selectNode(anchor);\n sel.removeAllRanges();\n sel.addRange(range);\n\n document.execCommand('unlink');\n this.context.invoke('editor.afterCommand');\n }\n}\n","// ImageTooltip.js - Hover tooltip for images inside the editor\n// Displays a horizontal action bar below (or above) the selected image,\n// similar in appearance and interaction to LinkTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst ICONS = {\n floatLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"6\" x2=\"22\" y2=\"6\"/><line x1=\"12\" y1=\"9\" x2=\"22\" y2=\"9\"/><line x1=\"12\" y1=\"12\" x2=\"22\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"14\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"2\" y1=\"6\" x2=\"12\" y2=\"6\"/><line x1=\"2\" y1=\"9\" x2=\"12\" y2=\"9\"/><line x1=\"2\" y1=\"12\" x2=\"12\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatNone: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"3\" y1=\"19\" x2=\"17\" y2=\"19\"/></svg>`,\n alignCenter: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"7\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\"/><line x1=\"6\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n originalSize:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/></svg>`,\n deleteImg: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n caption: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"11\" rx=\"2\"/><line x1=\"6\" y1=\"18\" x2=\"18\" y2=\"18\"/><line x1=\"9\" y1=\"21\" x2=\"15\" y2=\"21\"/></svg>`,\n rotateLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"/><polyline points=\"3 3 3 8 8 8\"/></svg>`,\n rotateRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 12a9 9 0 1 1-9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\"/><polyline points=\"21 3 21 8 16 8\"/></svg>`,\n crop: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 2 6 18 22 18\"/><polyline points=\"2 6 18 6 18 22\"/></svg>`,\n};\n\nconst SHOW_DELAY = 100;\nconst HIDE_DELAY = 180;\n\nexport class ImageTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeImg = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const img = e.target.closest('img');\n // Skip when the image is inside a link — LinkTooltip takes priority there\n if (img && editable.contains(img) && !img.closest('a[href]')) {\n this._scheduleShow(img);\n }\n }, { passive: true }),\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }, { passive: true }),\n // Hide when image is deselected by clicking elsewhere\n on(document, 'click', (e) => {\n if (this._activeImg && !this._activeImg.contains(e.target) && !this._el.contains(e.target)) {\n this._hide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.image;\n const el = createElement('div', {\n class: 'an-link-tooltip an-image-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label showing \"Image\"\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._floatLeftBtn = this._makeBtn(ICONS.floatLeft, L.floatLeft, () => this._setFloat('left'));\n this._floatNoneBtn = this._makeBtn(ICONS.floatNone, L.noFloat, () => this._setFloat(''));\n this._alignCenterBtn = this._makeBtn(ICONS.alignCenter, L.alignCenter, () => this._setCenter());\n this._floatRightBtn = this._makeBtn(ICONS.floatRight, L.floatRight, () => this._setFloat('right'));\n\n el.appendChild(this._floatLeftBtn);\n el.appendChild(this._floatNoneBtn);\n el.appendChild(this._alignCenterBtn);\n el.appendChild(this._floatRightBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._originalBtn = this._makeBtn(ICONS.originalSize, L.originalSize, () => this._resetSize());\n\n el.appendChild(this._originalBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n el.appendChild(this._makeBtn(ICONS.rotateLeft, L.rotateLeft, () => this._rotate(-90)));\n el.appendChild(this._makeBtn(ICONS.rotateRight, L.rotateRight, () => this._rotate(90)));\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._cropBtn = this._makeBtn(ICONS.crop, L.cropImage, () => this._crop());\n el.appendChild(this._cropBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._captionBtn = this._makeBtn(ICONS.caption, L.addCaption, () => this._toggleCaption());\n el.appendChild(this._captionBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._deleteBtn = this._makeBtn(ICONS.deleteImg, L.deleteImage, () => this._delete(), true);\n\n el.appendChild(this._deleteBtn);\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger ? 'an-link-tooltip-btn an-link-tooltip-btn--danger' : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(img) {\n if (this._activeImg === img && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeImg = img;\n this._show(img);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n // Always reset the hide timer so rapid mouseout→mouseover sequences\n // don't leave a stale timer that hides the tooltip prematurely.\n clearTimeout(this._hideTimer);\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show(img) {\n this._el.style.display = 'flex';\n // Defer positioning: offsetWidth on a newly-visible element forces layout\n requestAnimationFrame(() => {\n if (this._activeImg) this._positionNear(this._activeImg);\n });\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activeImg = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(img) {\n const rect = img.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 220;\n const tipH = this._el.offsetHeight || 32;\n const margin = 6;\n\n let top = rect.bottom + margin;\n let left = rect.left + (rect.width - tipW) / 2;\n\n if (top + tipH > window.innerHeight - margin) top = rect.top - tipH - margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const img = this._activeImg;\n if (!img) return;\n const target = img.closest('figure.an-figure') || img;\n target.style.float = value;\n target.style.display = '';\n // Clear explicit width set for centering so the figure is free to float\n if (target !== img) target.style.width = '';\n target.style.marginLeft = value === 'right' ? '12px' : '';\n target.style.marginRight = value === 'left' ? '12px' : '';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n _setCenter() {\n const img = this._activeImg;\n if (!img) return;\n const target = img.closest('figure.an-figure') || img;\n target.style.float = '';\n target.style.display = 'block';\n // C1/C3: use fit-content so the block figure shrinks to the image width;\n // without an explicit width, margin:auto has no effect on a 100%-wide block.\n if (target !== img) target.style.width = 'fit-content';\n target.style.marginLeft = 'auto';\n target.style.marginRight = 'auto';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n _resetSize() {\n const img = this._activeImg;\n if (!img) return;\n img.style.width = '';\n img.style.height = '';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n /**\n * Rotate the active image by `delta` degrees (±90).\n * Reads the existing rotate() value from the transform style so\n * repeated clicks accumulate correctly.\n * @param {number} delta\n */\n _rotate(delta) {\n const img = this._activeImg;\n if (!img) return;\n // Parse current rotation angle from inline transform\n const current = img.style.transform || '';\n const match = current.match(/rotate\\((-?[\\d.]+)deg\\)/);\n const prev = match ? parseFloat(match[1]) : 0;\n const next = (prev + delta + 360) % 360; // normalise to [0, 360)\n // Preserve any other transform functions (e.g. scale), replace only rotate()\n const cleaned = current.replace(/rotate\\(-?[\\d.]+deg\\)/, '').trim();\n img.style.transform = cleaned\n ? `${cleaned} rotate(${next}deg)`\n : next === 0 ? '' : `rotate(${next}deg)`;\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n _delete() {\n const img = this._activeImg;\n if (!img) return;\n this._hide();\n this.context.invoke('imageResizer.deselect');\n const figure = img.closest('figure.an-figure');\n if (figure && figure.parentNode) {\n figure.parentNode.removeChild(figure);\n } else if (img.parentNode) {\n img.parentNode.removeChild(img);\n }\n this.context.invoke('editor.afterCommand');\n }\n\n _crop() {\n const img = this._activeImg;\n if (!img) return;\n // Hide the tooltip while the crop overlay is active\n this._hide();\n // Delegate to imageCropOverlay module\n this.context.invoke('imageCropOverlay.open', img);\n }\n\n _toggleCaption() {\n const img = this._activeImg;\n if (!img) return;\n\n // If already inside a figure, move focus to the figcaption\n const existing = img.closest('figure.an-figure');\n if (existing) {\n const cap = existing.querySelector('figcaption.an-figcaption');\n if (cap) {\n this._hide();\n const range = document.createRange();\n range.selectNodeContents(cap);\n const sel = window.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(range); }\n }\n return;\n }\n\n // Wrap image in <figure><figcaption>\n const figure = document.createElement('figure');\n figure.className = 'an-figure';\n\n // Transfer existing alignment from <img> to <figure> (C4 fix)\n if (img.style.float) {\n figure.style.float = img.style.float;\n figure.style.marginLeft = img.style.marginLeft;\n figure.style.marginRight = img.style.marginRight;\n img.style.float = '';\n img.style.marginLeft = '';\n img.style.marginRight = '';\n } else if (img.style.display === 'block' && img.style.marginLeft === 'auto') {\n // C1/C3: use fit-content so the centered block figure tightly wraps the\n // image, making margin:auto actually centre it regardless of image width.\n figure.style.display = 'block';\n figure.style.width = 'fit-content';\n figure.style.marginLeft = 'auto';\n figure.style.marginRight = 'auto';\n img.style.display = '';\n img.style.marginLeft = '';\n img.style.marginRight = '';\n }\n const figcaption = document.createElement('figcaption');\n figcaption.className = 'an-figcaption';\n figcaption.textContent = 'Caption';\n\n img.parentNode.insertBefore(figure, img);\n figure.appendChild(img);\n figure.appendChild(figcaption);\n\n // Select caption text immediately\n const range = document.createRange();\n range.selectNodeContents(figcaption);\n const sel = window.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(range); }\n\n this.context.invoke('editor.afterCommand');\n // Re-sync the resize overlay: wrapping img in <figure> changes its layout position.\n this.context.invoke('imageResizer.updateOverlay');\n this._hide();\n }\n}\n","// VideoTooltip.js - Hover tooltip for video wrappers inside the editor\n// Displays a horizontal action bar below (or above) the selected video,\n// similar in appearance and interaction to LinkTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst ICONS = {\n floatLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"6\" x2=\"22\" y2=\"6\"/><line x1=\"12\" y1=\"9\" x2=\"22\" y2=\"9\"/><line x1=\"12\" y1=\"12\" x2=\"22\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"14\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"2\" y1=\"6\" x2=\"12\" y2=\"6\"/><line x1=\"2\" y1=\"9\" x2=\"12\" y2=\"9\"/><line x1=\"2\" y1=\"12\" x2=\"12\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatNone: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"3\" y1=\"19\" x2=\"17\" y2=\"19\"/></svg>`,\n alignCenter: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"7\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\"/><line x1=\"6\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n originalSize:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/></svg>`,\n deleteVideo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n preview: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"5 3 19 12 5 21 5 3\"/></svg>`,\n};\n\nconst SHOW_DELAY = 100;\nconst HIDE_DELAY = 180;\n\nexport class VideoTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeWrapper = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n this._previewMode = false;\n this._previewClickOff = null;\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n // The shield div sits on top of iframes — we detect hover via it or the wrapper\n const wrapper = e.target.closest('.an-video-wrapper');\n if (wrapper && editable.contains(wrapper)) {\n this._scheduleShow(wrapper);\n }\n }, { passive: true }),\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n if (\n this._activeWrapper &&\n !this._activeWrapper.contains(e.target) &&\n !this._el.contains(e.target)\n ) {\n this._hide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n if (this._previewMode) this._exitPreview();\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.video;\n const el = createElement('div', {\n class: 'an-link-tooltip an-video-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._floatLeftBtn = this._makeBtn(ICONS.floatLeft, L.floatLeft, () => this._setFloat('left'));\n this._floatNoneBtn = this._makeBtn(ICONS.floatNone, L.noFloat, () => this._setFloat(''));\n this._alignCenterBtn = this._makeBtn(ICONS.alignCenter, L.alignCenter, () => this._setCenter());\n this._floatRightBtn = this._makeBtn(ICONS.floatRight, L.floatRight, () => this._setFloat('right'));\n\n el.appendChild(this._floatLeftBtn);\n el.appendChild(this._floatNoneBtn);\n el.appendChild(this._alignCenterBtn);\n el.appendChild(this._floatRightBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._originalBtn = this._makeBtn(ICONS.originalSize, L.originalSize, () => this._resetSize());\n\n el.appendChild(this._originalBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._previewBtn = this._makeBtn(ICONS.preview, L.previewVideo, () => this._togglePreview());\n el.appendChild(this._previewBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._deleteBtn = this._makeBtn(ICONS.deleteVideo, L.deleteVideo, () => this._delete(), true);\n\n el.appendChild(this._deleteBtn);\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger ? 'an-link-tooltip-btn an-link-tooltip-btn--danger' : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(wrapper) {\n if (this._activeWrapper === wrapper && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeWrapper = wrapper;\n this._show(wrapper);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n // Keep tooltip alive while preview mode is active\n if (this._previewMode) return;\n clearTimeout(this._showTimer);\n this._showTimer = null;\n if (this._hideTimer) return;\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show(wrapper) {\n this._el.style.display = 'flex';\n // Defer: offsetWidth on a newly-visible element forces synchronous layout\n requestAnimationFrame(() => {\n if (this._activeWrapper) this._positionNear(this._activeWrapper);\n });\n }\n\n _hide() {\n if (this._previewMode) this._exitPreview();\n this._el.style.display = 'none';\n this._activeWrapper = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(wrapper) {\n const rect = wrapper.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 220;\n const tipH = this._el.offsetHeight || 32;\n const margin = 6;\n\n let top = rect.bottom + margin;\n let left = rect.left + (rect.width - tipW) / 2;\n\n if (top + tipH > window.innerHeight - margin) top = rect.top - tipH - margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n wrapper.style.float = value;\n wrapper.style.display = value ? 'inline-block' : '';\n wrapper.style.marginLeft = value === 'right' ? '12px' : '';\n wrapper.style.marginRight = value === 'left' ? '12px' : '';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('videoResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeWrapper) this._positionNear(this._activeWrapper); });\n }\n\n _setCenter() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n wrapper.style.float = '';\n wrapper.style.display = 'block';\n wrapper.style.marginLeft = 'auto';\n wrapper.style.marginRight = 'auto';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('videoResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeWrapper) this._positionNear(this._activeWrapper); });\n }\n\n _resetSize() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n const embed = wrapper.querySelector('iframe, video');\n wrapper.style.width = '';\n wrapper.style.height = '';\n if (embed) {\n embed.removeAttribute('width');\n embed.removeAttribute('height');\n embed.style.width = '';\n embed.style.height = '';\n }\n this.context.invoke('editor.afterCommand');\n this.context.invoke('videoResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeWrapper) this._positionNear(this._activeWrapper); });\n }\n\n _delete() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n this._hide();\n this.context.invoke('videoResizer.deselect');\n if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Preview mode — temporarily disables the shield so the video is interactive\n // ---------------------------------------------------------------------------\n\n _togglePreview() {\n if (this._previewMode) {\n this._exitPreview();\n } else {\n this._enterPreview();\n }\n }\n\n _enterPreview() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n this._previewMode = true;\n\n // Hide the shield so the iframe / video receives pointer events directly\n const shield = wrapper.querySelector('.an-video-shield');\n if (shield) shield.style.display = 'none';\n\n // Hide the resize overlay — it would block interaction with the embed\n this.context.invoke('videoResizer.deselect');\n\n // Visual feedback: button turns primary-coloured\n this._previewBtn.classList.add('an-link-tooltip-btn--copied');\n this._previewBtn.title = this.context.locale.tooltips.video.exitPreview;\n\n // Exit preview on mousedown outside the wrapper.\n // Using 'mousedown' (not 'click') so clicks inside an iframe\n // — which never bubble to the outer document — don't accidentally\n // leave preview mode stuck. For <video> elements, mousedown on the\n // video is inside the wrapper so contains() returns true → no exit.\n this._previewClickOff = (e) => {\n if (!wrapper.contains(e.target) && !this._el.contains(e.target)) {\n this._exitPreview();\n }\n };\n document.addEventListener('mousedown', this._previewClickOff, true);\n }\n\n _exitPreview() {\n this._previewMode = false;\n\n const wrapper = this._activeWrapper;\n if (wrapper) {\n // Restore the shield\n const shield = wrapper.querySelector('.an-video-shield');\n if (shield) shield.style.display = '';\n }\n\n // Reset button appearance\n this._previewBtn.classList.remove('an-link-tooltip-btn--copied');\n this._previewBtn.title = this.context.locale.tooltips.video.previewVideo;\n\n if (this._previewClickOff) {\n document.removeEventListener('mousedown', this._previewClickOff, true);\n this._previewClickOff = null;\n }\n }\n}\n","// TableTooltip.js - Hover tooltip for tables inside the editor\n// Shows a horizontal action bar above (or below) the hovered table,\n// similar in appearance and interaction to ImageTooltip / VideoTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 200;\n\n// ---------------------------------------------------------------------------\n// Table helpers — visual column index (accounts for colspan)\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the visual (logical) column index of a cell, taking colspan into\n * account for all preceding cells in the same row.\n * @param {HTMLTableCellElement} cell\n * @returns {number} 0-based visual column index, or -1 on failure\n */\nfunction getVisualColIndex(cell) {\n const row = cell.closest('tr');\n if (!row) return -1;\n let visualIdx = 0;\n for (const c of row.cells) {\n if (c === cell) return visualIdx;\n visualIdx += c.colSpan || 1;\n }\n return -1;\n}\n\n/**\n * Finds the first cell in a row whose visual start column equals visualIdx.\n * Returns null if no exact match (e.g. the column is spanned by a merged cell).\n * @param {HTMLTableRowElement} row\n * @param {number} visualIdx\n * @returns {HTMLTableCellElement|null}\n */\nfunction getCellAtVisualCol(row, visualIdx) {\n let vIdx = 0;\n for (const c of row.cells) {\n if (vIdx === visualIdx) return c;\n if (vIdx > visualIdx) break;\n vIdx += c.colSpan || 1;\n }\n return null;\n}\n\n/**\n * Finds the first cell whose visual range ends after visualIdx\n * (used for inserting a new column to the right of visualIdx).\n * @param {HTMLTableRowElement} row\n * @param {number} visualIdx\n * @returns {HTMLTableCellElement|null} reference cell for insertBefore, or null = append\n */\nfunction getCellAfterVisualCol(row, visualIdx) {\n let vIdx = 0;\n for (const c of row.cells) {\n vIdx += c.colSpan || 1;\n if (vIdx > visualIdx) {\n // next cell after the one that starts at / spans visualIdx\n const next = c.nextElementSibling;\n return (next && next.tagName === 'TD' || next && next.tagName === 'TH') ? next : null;\n }\n }\n return null;\n}\n\n/**\n * Build a 2D grid map of the table, accounting for both rowspan and colspan.\n *\n * gridMap[r][c] = the DOM cell occupying visual grid position (r, c).\n * cellPos = WeakMap: cell → { r, c, rs, cs } (top-left grid origin + span).\n *\n * Uses HTMLTableElement.rows which is scoped to the table itself and never\n * includes rows from nested tables.\n *\n * @param {HTMLTableElement} table\n * @returns {{ gridMap: Object, cellPos: WeakMap }}\n */\nfunction buildGridMap(table) {\n const rows = Array.from(table.rows);\n const gridMap = {};\n const cellPos = new WeakMap();\n rows.forEach((row, r) => {\n if (!gridMap[r]) gridMap[r] = {};\n let c = 0;\n for (const cell of row.cells) {\n // Skip positions already occupied by a rowspan from a previous row\n while (gridMap[r][c]) c++;\n const rs = cell.rowSpan || 1;\n const cs = cell.colSpan || 1;\n cellPos.set(cell, { r, c, rs, cs });\n for (let dr = 0; dr < rs; dr++) {\n if (!gridMap[r + dr]) gridMap[r + dr] = {};\n for (let dc = 0; dc < cs; dc++) {\n gridMap[r + dr][c + dc] = cell;\n }\n }\n c += cs;\n }\n });\n return { gridMap, cellPos };\n}\n\nconst ICONS = {\n rowAbove: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/><path d=\"M12 3v7\"/><path d=\"M9 7l3-4 3 4\"/></svg>`,\n rowBelow: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/><path d=\"M12 12v7\"/><path d=\"M9 17l3 4 3-4\"/></svg>`,\n deleteRow: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"15\" y1=\"15\" x2=\"21\" y2=\"21\"/><line x1=\"21\" y1=\"15\" x2=\"15\" y2=\"21\"/></svg>`,\n colLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><path d=\"M3 12h7\"/><path d=\"M7 8l-4 4 4 4\"/></svg>`,\n colRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><path d=\"M12 12h9\"/><path d=\"M17 8l4 4-4 4\"/></svg>`,\n deleteCol: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><line x1=\"15\" y1=\"6\" x2=\"21\" y2=\"12\"/><line x1=\"21\" y1=\"6\" x2=\"15\" y2=\"12\"/></svg>`,\n mergeCells: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"7\" width=\"8\" height=\"10\" rx=\"1\"/><rect x=\"14\" y=\"7\" width=\"8\" height=\"10\" rx=\"1\"/><path d=\"M10 12h4\"/><path d=\"M12 10l2 2-2 2\"/></svg>`,\n unmergeCells: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"1\"/><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" stroke-dasharray=\"2.5 2\"/><line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\" stroke-dasharray=\"2.5 2\"/><path d=\"M9 9 L6 12 L9 15\"/><path d=\"M15 9 L18 12 L15 15\"/></svg>`,\n colWidth: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"7\" y1=\"4\" x2=\"7\" y2=\"20\"/><line x1=\"17\" y1=\"4\" x2=\"17\" y2=\"20\"/><line x1=\"7\" y1=\"12\" x2=\"17\" y2=\"12\"/><path d=\"M10 9l-3 3 3 3\"/><path d=\"M14 9l3 3-3 3\"/></svg>`,\n rowHeight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"4\" y1=\"7\" x2=\"20\" y2=\"7\"/><line x1=\"4\" y1=\"17\" x2=\"20\" y2=\"17\"/><line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"17\"/><path d=\"M9 10l3-3 3 3\"/><path d=\"M9 14l3 3 3-3\"/></svg>`,\n tableBorder: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" stroke-width=\"1\"/><line x1=\"3\" y1=\"13\" x2=\"21\" y2=\"13\" stroke-width=\"2\"/><line x1=\"3\" y1=\"20\" x2=\"21\" y2=\"20\" stroke-width=\"3\"/></svg>`,\n deleteTable: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/><line x1=\"16\" y1=\"16\" x2=\"22\" y2=\"22\" stroke=\"#ef4444\"/><line x1=\"22\" y1=\"16\" x2=\"16\" y2=\"22\" stroke=\"#ef4444\"/></svg>`,\n selectCells: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z\" fill=\"currentColor\" opacity=\"0.15\"/><path d=\"M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z\"/></svg>`,\n};\n\nexport class TableTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeTable = null;\n this._activeCell = null; // last hovered td/th\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n this._sizePopover = null;\n this._sizeApply = null;\n this._sizeTitleEl = null;\n this._sizeInputEl = null;\n // Cell selection\n this._selectMode = false;\n this._selectedCells = [];\n this._selectStart = null;\n this._selectDragging = false;\n this._selectBtn = null;\n this._editable = null;\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n this._sizePopover = this._buildSizePopover();\n document.body.appendChild(this._sizePopover);\n\n const editable = this.context.layoutInfo.editable;\n this._editable = editable;\n\n // ── Cell selection drag ──────────────────────────────────────────────────\n const onSelMousedown = (e) => {\n if (!this._selectMode) return;\n const cell = e.target.closest('td, th');\n if (!cell || !editable.contains(cell)) return;\n // Don't interfere with col/row resize (inline cursor is set by resize logic)\n if (cell.style.cursor === 'col-resize' || cell.style.cursor === 'row-resize') return;\n e.preventDefault(); // suppress text-cursor placement while selecting cells\n this._activeTable = cell.closest('table');\n this._selectStart = cell;\n this._selectDragging = true;\n this._setSelection([cell]);\n };\n const onSelMousemove = (e) => {\n if (!this._selectMode || !this._selectDragging || !this._selectStart) return;\n const cell = e.target.closest('td, th');\n if (!cell || !editable.contains(cell)) return;\n if (cell.closest('table') !== this._activeTable) return;\n this._setSelection(this._getRectCells(this._selectStart, cell));\n };\n const onSelMouseup = () => { this._selectDragging = false; };\n\n this._disposers.push(\n on(editable, 'mousedown', onSelMousedown),\n on(editable, 'mousemove', onSelMousemove),\n on(document, 'mouseup', onSelMouseup),\n );\n // ────────────────────────────────────────────────────────────────────────\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const table = e.target.closest('table');\n if (table && editable.contains(table)) {\n const cell = e.target.closest('td, th');\n if (cell) this._activeCell = cell;\n this._scheduleShow(table);\n }\n }, { passive: true }),\n on(editable, 'mouseout', (e) => {\n if (this._selectMode) return; // keep tooltip alive during cell selection\n const to = e.relatedTarget;\n if (!to || (\n !editable.contains(to) &&\n !this._el.contains(to) &&\n !(this._sizePopover && this._sizePopover.contains(to))\n )) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n if (this._selectMode && this._activeTable && this._activeTable.contains(e.target)) return;\n if (this._activeTable &&\n !this._activeTable.contains(e.target) &&\n !this._el.contains(e.target) &&\n !(this._sizePopover && this._sizePopover.contains(e.target))) {\n this._hide();\n }\n }),\n );\n\n this._initResize();\n return this;\n }\n\n // ---------------------------------------------------------------------------\n // Column & row drag-resize\n // ---------------------------------------------------------------------------\n\n _initResize() {\n const editable = this.context.layoutInfo.editable;\n const HIT = 6; // px proximity threshold\n\n // Shared hover state\n let _nearCell = null;\n let _nearEdge = null; // 'col' | 'row' | null\n\n // Active drag state\n let _resizing = false;\n let _edge = null; // 'col' | 'row'\n let _startX = 0;\n let _startY = 0;\n let _startW = 0;\n let _startH = 0;\n let _colIdx = -1;\n let _colCells = null; // cells cached at drag-start — avoids querySelectorAll every frame\n let _row = null;\n let _table = null;\n let _rafDocMove = null; // pending rAF handle for resize drag\n let _rafEditorMove = null; // pending rAF handle for cursor detection\n\n const clearHover = () => {\n if (_nearCell) { _nearCell.style.cursor = ''; _nearCell = null; }\n _nearEdge = null;\n };\n\n const onEditorMove = (e) => {\n if (_resizing) return;\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) {\n clearHover();\n return;\n }\n // Throttle to one check per animation frame — getBoundingClientRect forces reflow\n if (_rafEditorMove !== null) return;\n const target = e.target;\n const clientX = e.clientX;\n const clientY = e.clientY;\n _rafEditorMove = requestAnimationFrame(() => {\n _rafEditorMove = null;\n const cell = target.closest('td, th');\n if (!cell || !editable.contains(cell)) { clearHover(); return; }\n if (_nearCell && _nearCell !== cell) _nearCell.style.cursor = '';\n const rect = cell.getBoundingClientRect();\n const onRight = Math.abs(clientX - rect.right) < HIT;\n const onBottom = Math.abs(clientY - rect.bottom) < HIT;\n if (onRight) {\n cell.style.cursor = 'col-resize';\n _nearCell = cell; _nearEdge = 'col';\n } else if (onBottom) {\n cell.style.cursor = 'row-resize';\n _nearCell = cell; _nearEdge = 'row';\n } else {\n clearHover();\n }\n });\n };\n\n const onEditorDown = (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n if (!_nearCell || !_nearEdge) return;\n _resizing = true;\n _edge = _nearEdge;\n _startX = e.clientX;\n _startY = e.clientY;\n _table = _nearCell.closest('table');\n if (_edge === 'col') {\n _startW = _nearCell.offsetWidth;\n _colIdx = getVisualColIndex(_nearCell);\n // Cache column cells once so onDocMove never runs querySelectorAll per frame.\n // F-1: skip merged cells (colSpan > 1) — setting width on a merged cell\n // distributes it equally across all spanned columns instead of resizing\n // only the target column. Rows that have an individual cell at this\n // visual column index are resized independently as expected.\n _colCells = _colIdx >= 0\n ? Array.from(_table.querySelectorAll('tr'))\n .map(r => getCellAtVisualCol(r, _colIdx))\n .filter(Boolean)\n .filter(c => (c.colSpan || 1) === 1)\n : [];\n document.body.style.cursor = 'col-resize';\n } else {\n _row = _nearCell.closest('tr');\n _startH = _row ? _row.offsetHeight : 40;\n document.body.style.cursor = 'row-resize';\n }\n document.body.style.userSelect = 'none';\n e.preventDefault();\n e.stopPropagation();\n };\n\n const onDocMove = (e) => {\n if (!_resizing) return;\n // Skip if a frame is already scheduled — avoids per-pixel style thrashing\n if (_rafDocMove !== null) return;\n const clientX = e.clientX;\n const clientY = e.clientY;\n _rafDocMove = requestAnimationFrame(() => {\n _rafDocMove = null;\n if (_edge === 'col') {\n const newW = Math.max(30, _startW + (clientX - _startX));\n for (const c of _colCells) {\n c.style.width = `${newW}px`;\n c.style.minWidth = `${newW}px`;\n }\n } else {\n const newH = Math.max(20, _startH + (clientY - _startY));\n if (_row) {\n for (const c of _row.cells) {\n c.style.height = `${newH}px`;\n c.style.minHeight = `${newH}px`;\n }\n }\n }\n });\n };\n\n const onDocUp = () => {\n if (!_resizing) return;\n // Cancel any in-flight rAF so stale writes don't land after mouseup\n if (_rafDocMove !== null) { cancelAnimationFrame(_rafDocMove); _rafDocMove = null; }\n _resizing = false;\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n _edge = null;\n _table = null;\n _row = null;\n _colIdx = -1;\n _colCells = null;\n this.context.invoke('editor.afterCommand');\n };\n\n this._disposers.push(\n on(editable, 'mousemove', onEditorMove),\n on(editable, 'mousedown', onEditorDown),\n on(document, 'mousemove', onDocMove),\n on(document, 'mouseup', onDocUp),\n );\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n if (this._sizePopover && this._sizePopover.parentNode) {\n this._sizePopover.parentNode.removeChild(this._sizePopover);\n }\n this._sizePopover = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build tooltip bar\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.table;\n const el = createElement('div', {\n class: 'an-link-tooltip an-table-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(this._sep());\n\n // Select-cells toggle\n this._selectBtn = this._makeBtn(ICONS.selectCells, L.selectCells, () => this._toggleSelectMode());\n el.appendChild(this._selectBtn);\n\n el.appendChild(this._sep());\n\n // Row operations\n el.appendChild(this._makeBtn(ICONS.rowAbove, L.addRowAbove, () => this._addRow('above')));\n el.appendChild(this._makeBtn(ICONS.rowBelow, L.addRowBelow, () => this._addRow('below')));\n el.appendChild(this._makeBtn(ICONS.deleteRow, L.deleteRow, () => this._deleteRow()));\n\n el.appendChild(this._sep());\n\n // Column operations\n el.appendChild(this._makeBtn(ICONS.colLeft, L.addColumnLeft, () => this._addColumn('left')));\n el.appendChild(this._makeBtn(ICONS.colRight, L.addColumnRight, () => this._addColumn('right')));\n el.appendChild(this._makeBtn(ICONS.deleteCol, L.deleteColumn, () => this._deleteColumn()));\n\n el.appendChild(this._sep());\n\n // Merge cells\n el.appendChild(this._makeBtn(ICONS.mergeCells, L.mergeCells, () => this._mergeCells()));\n el.appendChild(this._makeBtn(ICONS.unmergeCells, L.unmergeCells, () => this._unmergeCells()));\n\n el.appendChild(this._sep());\n\n // Resize\n el.appendChild(this._makeBtn(ICONS.colWidth, L.columnWidth, () => this._openSizePopover('col')));\n el.appendChild(this._makeBtn(ICONS.rowHeight, L.rowHeight, () => this._openSizePopover('row')));\n el.appendChild(this._makeBtn(ICONS.tableBorder,L.tableBorderWidth, () => this._openSizePopover('border')));\n\n el.appendChild(this._sep());\n\n // Delete table (danger)\n el.appendChild(this._makeBtn(ICONS.deleteTable, L.deleteTable, () => this._deleteTable(), true));\n\n // Keep tooltip alive while hovering.\n // Don't schedule hide on mouseleave when the size popover is open —\n // the user is moving the mouse toward it.\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => {\n if (this._selectMode) return; // keep tooltip alive during cell selection\n if (this._sizePopover && this._sizePopover.style.display !== 'none') return;\n this._scheduleHide();\n }),\n );\n\n return el;\n }\n\n _sep() {\n return createElement('div', { class: 'an-link-tooltip-sep' });\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger\n ? 'an-link-tooltip-btn an-link-tooltip-btn--danger'\n : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(table) {\n if (this._activeTable === table && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeTable = table;\n this._show();\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n if (this._hideTimer) return;\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show() {\n if (!this._activeTable) return;\n this._el.style.display = 'flex';\n // Defer: offsetWidth on a newly-visible element forces layout synchronously\n requestAnimationFrame(() => {\n if (this._activeTable) this._positionNear(this._activeTable);\n });\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activeTable = null;\n this._activeCell = null;\n // Reset select mode\n if (this._selectMode) {\n this._selectMode = false;\n if (this._selectBtn) this._selectBtn.classList.remove('an-link-tooltip-btn--active');\n if (this._editable) this._editable.classList.remove('an-table-select-mode');\n }\n this._clearSelection();\n this._clearTimers();\n this._hideSizePopover();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(table) {\n if (!table) return;\n const rect = table.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 400;\n const tipH = this._el.offsetHeight || 30;\n const margin = 6;\n\n // Center horizontally over the table; prefer above it\n let left = rect.left + (rect.width - tipW) / 2;\n let top = rect.top - tipH - margin;\n\n if (top < margin) top = rect.bottom + margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n this._el.style.left = `${left}px`;\n this._el.style.top = `${top}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Helper: get active cell (fallback to first td/th in table)\n // ---------------------------------------------------------------------------\n\n _getCell() {\n // Prefer the cell under the current text cursor (most intuitive for operations)\n const sel = window.getSelection();\n if (sel && sel.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const cellFromSel = container && container.closest && container.closest('td, th');\n if (cellFromSel && this._activeTable && this._activeTable.contains(cellFromSel)) {\n return cellFromSel;\n }\n }\n return this._activeCell\n || (this._activeTable && this._activeTable.querySelector('td, th'));\n }\n\n // ---------------------------------------------------------------------------\n // Cell selection helpers\n // ---------------------------------------------------------------------------\n\n _toggleSelectMode() {\n this._selectMode = !this._selectMode;\n if (this._selectBtn) {\n this._selectBtn.classList.toggle('an-link-tooltip-btn--active', this._selectMode);\n }\n if (this._editable) {\n this._editable.classList.toggle('an-table-select-mode', this._selectMode);\n }\n if (!this._selectMode) {\n this._clearSelection();\n }\n }\n\n _clearSelection() {\n this._selectedCells.forEach((c) => c.classList.remove('an-cell-selected'));\n this._selectedCells = [];\n this._selectStart = null;\n }\n\n _setSelection(cells) {\n // Remove highlight from cells no longer in selection\n this._selectedCells.forEach((c) => {\n if (!cells.includes(c)) c.classList.remove('an-cell-selected');\n });\n this._selectedCells = cells;\n cells.forEach((c) => c.classList.add('an-cell-selected'));\n }\n\n /**\n * Returns all cells in the rectangular area between startCell and endCell,\n * correctly handling rowspan/colspan by using the grid map.\n * The rect is expanded iteratively until it is stable — this ensures any\n * merged cell that starts outside the initial rect but spans into it is\n * fully included.\n */\n _getRectCells(startCell, endCell) {\n if (!startCell) return [];\n if (!endCell || startCell === endCell) return [startCell];\n const table = startCell.closest('table');\n if (!table || !table.contains(endCell)) return [startCell];\n\n const { gridMap, cellPos } = buildGridMap(table);\n const sp = cellPos.get(startCell);\n const ep = cellPos.get(endCell);\n if (!sp || !ep) return [startCell];\n\n let minR = Math.min(sp.r, ep.r);\n let maxR = Math.max(sp.r + sp.rs - 1, ep.r + ep.rs - 1);\n let minC = Math.min(sp.c, ep.c);\n let maxC = Math.max(sp.c + sp.cs - 1, ep.c + ep.cs - 1);\n\n // Iteratively expand until stable — handles spans that exceed the current rect\n let changed = true;\n while (changed) {\n changed = false;\n for (let r = minR; r <= maxR; r++) {\n const rowMap = gridMap[r];\n if (!rowMap) continue;\n for (let c = minC; c <= maxC; c++) {\n const cell = rowMap[c];\n if (!cell) continue;\n const pos = cellPos.get(cell);\n if (!pos) continue;\n if (pos.r < minR) { minR = pos.r; changed = true; }\n if (pos.r + pos.rs - 1 > maxR) { maxR = pos.r + pos.rs - 1; changed = true; }\n if (pos.c < minC) { minC = pos.c; changed = true; }\n if (pos.c + pos.cs - 1 > maxC) { maxC = pos.c + pos.cs - 1; changed = true; }\n }\n }\n }\n\n // Collect unique cells in document order\n const seen = new Set();\n const result = [];\n for (let r = minR; r <= maxR; r++) {\n const rowMap = gridMap[r];\n if (!rowMap) continue;\n for (let c = minC; c <= maxC; c++) {\n const cell = rowMap[c];\n if (cell && !seen.has(cell)) {\n seen.add(cell);\n result.push(cell);\n }\n }\n }\n return result.length > 0 ? result : [startCell];\n }\n\n /**\n * Returns the active cell set: user-selected cells when available,\n * otherwise the single active/cursor cell.\n * @returns {HTMLTableCellElement[]}\n */\n _getSelectedCells() {\n return this._selectedCells.length > 0\n ? this._selectedCells\n : [this._getCell()].filter(Boolean);\n }\n\n // ---------------------------------------------------------------------------\n // Table operations\n // ---------------------------------------------------------------------------\n\n _addRow(position) {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const allRows = Array.from(table.querySelectorAll('tr'));\n const selectedRows = [...new Set(cells.map((c) => c.closest('tr')).filter(Boolean))];\n // Reference row: topmost for 'above', bottommost for 'below'\n const refRow = selectedRows.reduce((best, r) => {\n const bi = allRows.indexOf(best);\n const ri = allRows.indexOf(r);\n return position === 'above' ? (ri < bi ? r : best) : (ri > bi ? r : best);\n });\n const colCount = Array.from(refRow.cells).reduce((sum, c) => sum + (c.colSpan || 1), 0);\n const newRow = document.createElement('tr');\n const refCells = Array.from(refRow.cells);\n for (let i = 0; i < colCount; i++) {\n const td = createElement('td', {}, ['\\u00a0']);\n const ref = refCells[i];\n if (ref && ref.style.width) td.style.width = ref.style.width;\n if (ref && ref.style.minWidth) td.style.minWidth = ref.style.minWidth;\n newRow.appendChild(td);\n }\n if (position === 'above') refRow.parentElement?.insertBefore(newRow, refRow);\n else refRow.insertAdjacentElement('afterend', newRow);\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _addColumn(position) {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const colIndices = cells.map((c) => getVisualColIndex(c));\n const targetColIdx = position === 'left' ? Math.min(...colIndices) : Math.max(...colIndices);\n const rows = Array.from(table.querySelectorAll('tr'));\n const refs = rows.map((r) => position === 'left'\n ? getCellAtVisualCol(r, targetColIdx)\n : getCellAfterVisualCol(r, targetColIdx));\n const isHeaders = rows.map((r) => r.closest('thead') !== null);\n rows.forEach((r, i) => {\n r.insertBefore(createElement(isHeaders[i] ? 'th' : 'td', {}, ['\\u00a0']), refs[i]);\n });\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _deleteRow() {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const tbody = table.querySelector('tbody');\n const totalBodyRows = tbody\n ? tbody.querySelectorAll('tr').length\n : table.querySelectorAll('tr').length;\n const selectedRows = [...new Set(cells.map((c) => c.closest('tr')).filter(Boolean))];\n const bodyRowsToDelete = selectedRows.filter((r) => r.closest('tbody'));\n // Guard: keep at least one body row\n if (bodyRowsToDelete.length >= totalBodyRows) return;\n this._activeCell = null;\n this._clearSelection();\n selectedRows.forEach((r) => r.parentElement?.removeChild(r));\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _deleteColumn() {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const tableRows = Array.from(table.querySelectorAll('tr'));\n if (tableRows[0] && tableRows[0].cells.length <= 1) return; // guard: keep ≥1 col\n const colIndices = [...new Set(cells.map((c) => getVisualColIndex(c)))];\n if (colIndices.length >= (tableRows[0]?.cells.length ?? 1)) return;\n // Collect all cell references upfront before any removal (avoids stale visual indices)\n const cellsToDelete = [];\n colIndices.forEach((colIdx) => {\n tableRows.forEach((r) => {\n const c = getCellAtVisualCol(r, colIdx);\n if (c) cellsToDelete.push(c);\n });\n });\n this._activeCell = null;\n this._clearSelection();\n cellsToDelete.forEach((c) => c.parentElement?.removeChild(c));\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _mergeCells() {\n const cell = this._getCell();\n if (!cell) return;\n const table = cell.closest('table');\n if (!table) return;\n\n // Prefer user panel-selected cells; fall back to text-selection range\n let selected = this._getSelectedCells().filter((c) => table.contains(c));\n if (selected.length < 2) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n const allCells = Array.from(table.querySelectorAll('td, th'));\n selected = allCells.filter((c) => {\n try { return range.intersectsNode(c); } catch { return false; }\n });\n if (selected.length < 2) return;\n }\n\n const { gridMap, cellPos } = buildGridMap(table);\n\n // Bounding rect that encompasses every selected cell's full span\n let minR = Infinity, maxR = -Infinity, minC = Infinity, maxC = -Infinity;\n selected.forEach((c) => {\n const pos = cellPos.get(c);\n if (!pos) return;\n if (pos.r < minR) minR = pos.r;\n if (pos.r + pos.rs - 1 > maxR) maxR = pos.r + pos.rs - 1;\n if (pos.c < minC) minC = pos.c;\n if (pos.c + pos.cs - 1 > maxC) maxC = pos.c + pos.cs - 1;\n });\n if (minR === Infinity) return;\n\n // Collect every unique cell in the bounding rect\n const seen = new Set();\n const rectCells = [];\n for (let r = minR; r <= maxR; r++) {\n const rowMap = gridMap[r];\n if (!rowMap) continue;\n for (let c = minC; c <= maxC; c++) {\n const tc = rowMap[c];\n if (tc && !seen.has(tc)) { seen.add(tc); rectCells.push(tc); }\n }\n }\n if (rectCells.length < 2) return;\n\n const first = rectCells[0];\n first.colSpan = maxC - minC + 1;\n first.rowSpan = maxR - minR + 1;\n first.style.verticalAlign = 'middle';\n first.innerHTML = rectCells.map((c) => c.innerHTML).join('');\n rectCells.slice(1).forEach((c) => c.parentElement?.removeChild(c));\n\n this._clearSelection();\n this.context.invoke('editor.afterCommand');\n }\n\n _deleteTable() {\n const table = this._activeTable;\n if (!table) return;\n this._hide();\n if (table.parentNode) table.parentNode.removeChild(table);\n this.context.invoke('editor.afterCommand');\n }\n\n _unmergeCells() {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const mergedCells = cells.filter(\n (c) => table.contains(c) && ((c.colSpan || 1) > 1 || (c.rowSpan || 1) > 1)\n );\n if (!mergedCells.length) return;\n mergedCells.forEach((cell) => {\n if (table.contains(cell)) this._unmergeOne(cell, table);\n });\n this._clearSelection();\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Split a single merged cell (colspan/rowspan > 1) back into individual cells.\n * New cells are empty ( ); the original cell retains its content.\n * @param {HTMLTableCellElement} cell\n * @param {HTMLTableElement} table\n */\n _unmergeOne(cell, table) {\n const cs = cell.colSpan || 1;\n const rs = cell.rowSpan || 1;\n if (cs === 1 && rs === 1) return;\n\n // Build grid map from current DOM state (before any mutation)\n const { cellPos } = buildGridMap(table);\n const pos = cellPos.get(cell);\n if (!pos) return;\n\n const { r, c } = pos;\n const tableRows = Array.from(table.rows);\n const tag = cell.tagName.toLowerCase(); // preserve td / th\n\n // Reset the original cell\n cell.rowSpan = 1;\n cell.colSpan = 1;\n cell.style.verticalAlign = '';\n\n // Same row: insert (cs - 1) sibling cells after the original cell\n if (cs > 1) {\n const insertRef = cell.nextElementSibling;\n for (let dc = 1; dc < cs; dc++) {\n tableRows[r].insertBefore(createElement(tag, {}, ['\\u00a0']), insertRef);\n }\n }\n\n // Rows below: insert cs cells at the correct visual column position (for rowspan)\n for (let dr = 1; dr < rs; dr++) {\n const targetRow = tableRows[r + dr];\n if (!targetRow) continue;\n // Find the first cell in this row whose visual-col origin is beyond c\n // (using cellPos built before mutations — valid for these untouched rows)\n let ref = null;\n for (const tc of targetRow.cells) {\n const tp = cellPos.get(tc);\n if (tp && tp.c > c) { ref = tc; break; }\n }\n for (let dc = 0; dc < cs; dc++) {\n targetRow.insertBefore(createElement(tag, {}, ['\\u00a0']), ref);\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Size popover (column width / row height)\n // ---------------------------------------------------------------------------\n\n _buildSizePopover() {\n const popover = createElement('div', { class: 'an-size-popover' });\n popover.style.display = 'none';\n\n const titleEl = createElement('div', { class: 'an-size-popover-title' });\n const body = createElement('div', { class: 'an-size-popover-body' });\n const inputEl = createElement('input', {\n type: 'number', class: 'an-size-input', min: '1', max: '2000', step: '1',\n });\n const unitEl = createElement('span', { class: 'an-size-unit' }, ['px']);\n body.appendChild(inputEl);\n body.appendChild(unitEl);\n\n const actionsEl = createElement('div', { class: 'an-size-popover-actions' });\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = this.context.locale.tooltips.table.cancelBtn;\n const applyBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n applyBtn.textContent = this.context.locale.tooltips.table.applyBtn;\n actionsEl.appendChild(cancelBtn);\n actionsEl.appendChild(applyBtn);\n\n popover.appendChild(titleEl);\n popover.appendChild(body);\n popover.appendChild(actionsEl);\n\n this._sizeTitleEl = titleEl;\n this._sizeInputEl = inputEl;\n this._sizeApply = null;\n\n const d1 = on(applyBtn, 'click', () => {\n const val = parseInt(this._sizeInputEl.value, 10);\n if (val > 0 && typeof this._sizeApply === 'function') this._sizeApply(val);\n this._hideSizePopover();\n });\n const d2 = on(cancelBtn, 'click', () => this._hideSizePopover());\n const d3 = on(inputEl, 'keydown', (e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (e.key === 'Escape') this._hideSizePopover();\n });\n const d4 = on(document, 'click', (e) => {\n if (this._sizePopover &&\n this._sizePopover.style.display !== 'none' &&\n !this._sizePopover.contains(e.target) &&\n !this._el.contains(e.target)) {\n this._hideSizePopover();\n }\n });\n // Keep the tooltip/popover alive while the mouse is over the popover.\n const d5 = on(popover, 'mouseenter', () => this._clearTimers());\n const d6 = on(popover, 'mouseleave', () => this._scheduleHide());\n this._disposers.push(d1, d2, d3, d4, d5, d6);\n return popover;\n }\n\n _openSizePopover(type) {\n const cell = this._getCell();\n if (!cell || !this._sizePopover) return;\n\n if (type === 'border') {\n const table = cell.closest('table');\n if (!table) return;\n const firstCell = table.querySelector('td, th');\n const currentPx = firstCell\n ? (parseInt(firstCell.style.borderWidth, 10) ||\n parseInt(window.getComputedStyle(firstCell).borderWidth, 10) || 1)\n : 1;\n this._sizeTitleEl.textContent = this.context.locale.tooltips.table.tableBorderWidthPx;\n this._sizeInputEl.min = '0';\n this._sizeInputEl.max = '10';\n this._sizeInputEl.value = currentPx;\n this._sizeApply = (val) => {\n const cells = Array.from(table.querySelectorAll('td, th'));\n if (val === 0) {\n cells.forEach((c) => { c.style.borderWidth = '0'; c.style.borderStyle = 'none'; });\n } else {\n cells.forEach((c) => { c.style.borderWidth = `${val}px`; c.style.borderStyle = 'solid'; });\n }\n this.context.invoke('editor.afterCommand');\n };\n } else {\n const isCol = type === 'col';\n const activeCells = this._getSelectedCells().filter((c) => {\n const t = c.closest('table');\n return t && t === cell.closest('table');\n });\n this._sizeTitleEl.textContent = isCol\n ? this.context.locale.tooltips.table.columnWidthPx\n : this.context.locale.tooltips.table.rowHeightPx;\n this._sizeInputEl.min = '1';\n this._sizeInputEl.max = '2000';\n this._sizeInputEl.value = isCol\n ? (cell.offsetWidth || 120)\n : (cell.closest('tr') ? (cell.closest('tr').offsetHeight || 40) : 40);\n this._sizeApply = (val) => {\n const table = cell.closest('table');\n if (!table) return;\n if (isCol) {\n // Apply to all selected columns (or just the current column)\n const colIndices = [...new Set(activeCells.map((c) => getVisualColIndex(c)))];\n const tableRows = Array.from(table.querySelectorAll('tr'));\n colIndices.forEach((colIdx) => {\n tableRows.forEach((r) => {\n const c = getCellAtVisualCol(r, colIdx);\n // F-1: skip merged cells — same reason as drag-resize _colCells.\n if (c && (c.colSpan || 1) === 1) { c.style.width = `${val}px`; c.style.minWidth = `${val}px`; }\n });\n });\n } else {\n // Apply to all selected rows (or just the current row)\n const selectedRows = [...new Set(activeCells.map((c) => c.closest('tr')).filter(Boolean))];\n selectedRows.forEach((row) => {\n for (const c of row.cells) { c.style.height = `${val}px`; c.style.minHeight = `${val}px`; }\n });\n }\n this.context.invoke('editor.afterCommand');\n };\n }\n\n this._sizePopover.style.display = 'block';\n requestAnimationFrame(() => {\n if (!this._sizePopover || !this._el) return;\n const tipRect = this._el.getBoundingClientRect();\n const pw = this._sizePopover.offsetWidth || 220;\n const ph = this._sizePopover.offsetHeight || 110;\n let left = tipRect.left;\n let top = tipRect.bottom + 6;\n if (left + pw > window.innerWidth - 8) left = window.innerWidth - pw - 8;\n if (top + ph > window.innerHeight - 8) top = tipRect.top - ph - 6;\n this._sizePopover.style.left = `${left}px`;\n this._sizePopover.style.top = `${top}px`;\n if (this._sizeInputEl) { this._sizeInputEl.focus(); this._sizeInputEl.select(); }\n });\n }\n\n _hideSizePopover() {\n if (this._sizePopover) this._sizePopover.style.display = 'none';\n this._sizeApply = null;\n }\n}\n","// CodeTooltip.js - Hover tooltip for <pre> code blocks inside the editor\n// Shows a horizontal action bar above (or below) the hovered code block,\n// consistent in appearance and interaction with ImageTooltip / TableTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst SHOW_DELAY = 100;\nconst HIDE_DELAY = 180;\n\n// Cached regex for extracting language class — defined once at module level.\nconst _LANG_CLASS_RE = /language-(\\S+)/;\n\nconst ICONS = {\n copy: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`,\n wrapOn: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><path d=\"M3 12h15a3 3 0 0 1 0 6H3\"/><polyline points=\"6 15 3 18 6 21\"/></svg>`,\n toParagraph:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M13 4v16\"/><path d=\"M17 4v16\"/><path d=\"M9 4h8a4 4 0 0 1 0 8H9V4z\"/></svg>`,\n deleteCode: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n};\n\nexport class CodeTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activePre = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n this._copyBtn = null;\n this._langSelect = null;\n this._prismScript = null; // script element while Prism is loading\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n this._ensurePrism();\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const pre = e.target.closest('pre');\n if (pre && editable.contains(pre)) {\n this._scheduleShow(pre);\n }\n }),\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n on(document, 'click', (e) => {\n if (this._activePre &&\n !this._activePre.contains(e.target) &&\n !this._el.contains(e.target)) {\n this._hide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.code;\n const el = createElement('div', {\n class: 'an-link-tooltip an-code-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(this._sep());\n\n // Language selector\n this._langSelect = createElement('select', {\n class: 'an-code-lang-select',\n title: L.syntaxLanguage,\n 'aria-label': L.syntaxAriaLabel,\n });\n const LANGUAGES = [\n ['', 'Plain text'], ['javascript', 'JavaScript'], ['typescript', 'TypeScript'],\n ['python', 'Python'], ['html', 'HTML'], ['css', 'CSS'], ['json', 'JSON'],\n ['xml', 'XML'], ['bash', 'Bash / Shell'], ['sql', 'SQL'],\n ['java', 'Java'], ['csharp', 'C#'], ['php', 'PHP'], ['ruby', 'Ruby'],\n ['go', 'Go'], ['rust', 'Rust'], ['cpp', 'C++'], ['c', 'C'],\n ['kotlin', 'Kotlin'], ['swift', 'Swift'],\n ];\n LANGUAGES.forEach(([value, label]) => {\n const opt = createElement('option', { value });\n opt.textContent = label;\n this._langSelect.appendChild(opt);\n });\n this._disposers.push(on(this._langSelect, 'change', () => this._onLangChange()));\n el.appendChild(this._langSelect);\n\n el.appendChild(this._sep());\n\n // Copy code\n this._copyBtn = this._makeBtn(ICONS.copy, L.copyCode, () => this._copyCode());\n\n el.appendChild(this._copyBtn);\n\n el.appendChild(this._sep());\n\n // Toggle word-wrap\n this._wrapBtn = this._makeBtn(ICONS.wrapOn, L.toggleWordWrap, () => this._toggleWrap());\n el.appendChild(this._wrapBtn);\n\n el.appendChild(this._sep());\n\n // Convert to normal paragraph\n el.appendChild(this._makeBtn(ICONS.toParagraph, L.convertToParagraph, () => this._toParagraph()));\n\n el.appendChild(this._sep());\n\n // Delete block\n el.appendChild(this._makeBtn(ICONS.deleteCode, L.deleteCodeBlock, () => this._delete(), true));\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n _sep() {\n return createElement('div', { class: 'an-link-tooltip-sep' });\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger ? 'an-link-tooltip-btn an-link-tooltip-btn--danger' : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(pre) {\n if (this._activePre === pre && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activePre = pre;\n this._syncWrapBtn();\n this._syncLangSelect();\n this._show(pre);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n // Always reset the hide timer so rapid mouseout→mouseover sequences\n // don't leave a stale timer that hides the tooltip prematurely.\n clearTimeout(this._hideTimer);\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show(pre) {\n this._el.style.display = 'flex';\n this._positionNear(pre);\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activePre = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(pre) {\n const rect = pre.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 260;\n const tipH = this._el.offsetHeight || 32;\n const margin = 6;\n\n // Prefer above the block; fall back to below\n let top = rect.top - tipH - margin;\n let left = rect.left + (rect.width - tipW) / 2;\n\n if (top < margin) top = rect.bottom + margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n // Tooltip uses position:fixed, so viewport coordinates are used directly.\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Sync wrap-button active state\n // ---------------------------------------------------------------------------\n\n _syncWrapBtn() {\n if (!this._activePre || !this._wrapBtn) return;\n const wrapped = (this._activePre.style.whiteSpace || '').includes('pre-wrap')\n || window.getComputedStyle(this._activePre).whiteSpace === 'pre-wrap';\n this._wrapBtn.classList.toggle('active', wrapped);\n this._wrapBtn.title = wrapped\n ? this.context.locale.tooltips.code.disableWordWrap\n : this.context.locale.tooltips.code.enableWordWrap;\n }\n\n _syncLangSelect() {\n if (!this._activePre || !this._langSelect) return;\n const codeEl = this._activePre.querySelector('code');\n const fromAttr = this._activePre.getAttribute('data-language') || '';\n const fromClass = codeEl ? (_LANG_CLASS_RE.exec(codeEl.className) || [])[1] || '' : '';\n this._langSelect.value = fromAttr || fromClass || '';\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _copyCode() {\n const pre = this._activePre;\n if (!pre) return;\n const text = pre.textContent || '';\n if (navigator.clipboard) {\n navigator.clipboard.writeText(text).then(() => this._flashCopied()).catch(() => {});\n } else {\n // Fallback for older browsers\n const ta = document.createElement('textarea');\n ta.value = text;\n ta.style.cssText = 'position:fixed;opacity:0;top:0;left:0';\n document.body.appendChild(ta);\n ta.select();\n try { document.execCommand('copy'); this._flashCopied(); } catch (_) {}\n document.body.removeChild(ta);\n }\n }\n\n _flashCopied() {\n if (!this._copyBtn) return;\n const original = this._copyBtn.innerHTML;\n this._copyBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n this._copyBtn.classList.add('an-link-tooltip-btn--copied');\n setTimeout(() => {\n if (this._copyBtn) {\n this._copyBtn.innerHTML = original;\n this._copyBtn.classList.remove('an-link-tooltip-btn--copied');\n }\n }, 1400);\n }\n\n _toggleWrap() {\n const pre = this._activePre;\n if (!pre) return;\n const isWrapped = pre.style.whiteSpace === 'pre-wrap';\n pre.style.whiteSpace = isWrapped ? 'pre' : 'pre-wrap';\n this._syncWrapBtn();\n this.context.invoke('editor.afterCommand');\n this._positionNear(pre);\n }\n\n _onLangChange() {\n const pre = this._activePre;\n if (!pre) return;\n const lang = this._langSelect.value;\n\n // Ensure a <code> child exists (Prism targets <pre><code class=\"language-xxx\">)\n let codeEl = pre.querySelector('code');\n if (!codeEl) {\n codeEl = document.createElement('code');\n codeEl.innerHTML = pre.innerHTML;\n pre.innerHTML = '';\n pre.appendChild(codeEl);\n }\n\n codeEl.className = lang ? `language-${lang}` : '';\n // Mirror language class on <pre> so Prism CSS theme targets it (pre[class*='language-'])\n pre.className = lang ? `language-${lang}` : '';\n if (lang) {\n pre.setAttribute('data-language', lang);\n } else {\n pre.removeAttribute('data-language');\n }\n\n // Trigger Prism if available.\n // contenteditable stores line breaks as <br> elements; Prism reads textContent\n // which drops <br> entirely, collapsing all lines into one. Convert first.\n const applyPrism = () => {\n codeEl.querySelectorAll('br').forEach((br) => br.replaceWith('\\n'));\n window.Prism.highlightElement(codeEl);\n this.context.invoke('editor.afterCommand');\n };\n\n if (lang) {\n if (typeof window.Prism !== 'undefined') {\n // Grammar already loaded — highlight immediately\n if (window.Prism.languages[lang]) {\n applyPrism();\n return;\n }\n // Grammar not in core bundle — load the component script first\n this._loadPrismComponent(lang, applyPrism);\n return;\n } else if (this._prismScript) {\n // Prism core is still loading — highlight once it arrives, then load grammar if needed\n this._prismScript.addEventListener('load', () => {\n if (window.Prism.languages[lang]) {\n applyPrism();\n } else {\n this._loadPrismComponent(lang, applyPrism);\n }\n }, { once: true });\n return;\n }\n }\n\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Loads Prism.js + CSS from CDN when options.codeHighlight is true.\n * Called once at initialize time. Fire-and-forget; errors are silent.\n */\n _ensurePrism() {\n if (!this.context.options.codeHighlight || window.Prism) return;\n const cdn = this.context.options.codeHighlightCDN;\n const themeHref = `${cdn}/themes/prism-tomorrow.min.css`;\n const scriptSrc = `${cdn}/prism.min.js`;\n\n if (!document.querySelector(`link[href=\"${themeHref}\"]`)) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = themeHref;\n document.head.appendChild(link);\n }\n\n const existingScript = document.querySelector(`script[src=\"${scriptSrc}\"]`);\n if (existingScript) {\n this._prismScript = window.Prism ? null : existingScript;\n return;\n }\n\n const script = document.createElement('script');\n script.dataset.manual = ''; // prevent auto-highlight on load\n script.src = scriptSrc;\n this._prismScript = script;\n script.addEventListener('load', () => { this._prismScript = null; }, { once: true });\n document.head.appendChild(script);\n }\n\n /**\n * Dynamically loads a Prism language component script if not already available.\n * Prism core only bundles: markup, css, clike, javascript.\n * All other grammars (bash, python, etc.) need a component file.\n * @param {string} lang – Prism language slug (e.g. 'bash', 'python')\n * @param {Function} cb – called once the grammar is ready\n */\n _loadPrismComponent(lang, cb) {\n const cdn = this.context.options.codeHighlightCDN;\n const src = `${cdn}/components/prism-${lang}.min.js`;\n // Avoid loading the same component twice\n if (document.querySelector(`script[src=\"${src}\"]`)) {\n // Already in DOM — might still be loading; poll briefly then call cb\n const poll = setInterval(() => {\n if (window.Prism && window.Prism.languages[lang]) {\n clearInterval(poll);\n cb();\n }\n }, 50);\n setTimeout(() => clearInterval(poll), 3000); // give up after 3s\n return;\n }\n const s = document.createElement('script');\n s.src = src;\n s.addEventListener('load', cb, { once: true });\n document.head.appendChild(s);\n }\n\n _toParagraph() {\n const pre = this._activePre;\n if (!pre) return;\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n\n // Replace <pre> with <p> preserving lines as <br>\n const lines = (pre.textContent || '').split('\\n');\n const p = document.createElement('p');\n lines.forEach((line, i) => {\n if (i > 0) p.appendChild(document.createElement('br'));\n p.appendChild(document.createTextNode(line));\n });\n\n pre.parentNode.replaceChild(p, pre);\n this._hide();\n this.context.invoke('editor.afterCommand');\n }\n\n _delete() {\n const pre = this._activePre;\n if (!pre) return;\n this._hide();\n if (pre.parentNode) pre.parentNode.removeChild(pre);\n this.context.invoke('editor.afterCommand');\n }\n}\n","/**\n * EmojiDialog.js - Browse and insert Unicode emoji / symbols (UTF-8 / utf8mb4)\n * Click an emoji to insert it directly at the caret — no extra \"Insert\" step.\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// Emoji catalogue\n// ---------------------------------------------------------------------------\n\nconst EMOJI_CATS = [\n { id: 'smileys', label: 'Smileys' },\n { id: 'people', label: 'People' },\n { id: 'animals', label: 'Animals' },\n { id: 'food', label: 'Food' },\n { id: 'travel', label: 'Travel' },\n { id: 'objects', label: 'Objects' },\n { id: 'symbols', label: 'Symbols' },\n];\n\n// [emoji_char, search_keywords, category]\nconst EMOJI_LIST = [\n // Smileys & Emotions\n ['😀', 'grin smile happy face', 'smileys'],\n ['😃', 'happy smile big eyes', 'smileys'],\n ['😄', 'grinning smile laugh', 'smileys'],\n ['😁', 'beaming smile grin', 'smileys'],\n ['😆', 'laughing lol', 'smileys'],\n ['😅', 'sweat grin awkward', 'smileys'],\n ['🤣', 'rolling laugh rofl', 'smileys'],\n ['😂', 'tears laugh cry joy', 'smileys'],\n ['🙂', 'slight smile', 'smileys'],\n ['🙃', 'upside down smile', 'smileys'],\n ['😉', 'wink', 'smileys'],\n ['😊', 'blush smile happy', 'smileys'],\n ['😇', 'innocent halo angel', 'smileys'],\n ['🥰', 'hearts love adore', 'smileys'],\n ['😍', 'heart eyes love', 'smileys'],\n ['🤩', 'star eyes excited wow', 'smileys'],\n ['😘', 'kiss blow love', 'smileys'],\n ['😋', 'yum delicious tongue', 'smileys'],\n ['😛', 'tongue stuck out', 'smileys'],\n ['😜', 'wink tongue crazy', 'smileys'],\n ['🤪', 'zany crazy wild', 'smileys'],\n ['😝', 'squint tongue', 'smileys'],\n ['🤑', 'money mouth', 'smileys'],\n ['🤗', 'hugging hug', 'smileys'],\n ['🤔', 'thinking hmm', 'smileys'],\n ['🤨', 'raised eyebrow', 'smileys'],\n ['😐', 'neutral face', 'smileys'],\n ['😶', 'no mouth', 'smileys'],\n ['😏', 'smirk', 'smileys'],\n ['😒', 'unamused', 'smileys'],\n ['🙄', 'roll eyes', 'smileys'],\n ['😬', 'grimace', 'smileys'],\n ['😔', 'pensive sad', 'smileys'],\n ['😪', 'sleepy tired', 'smileys'],\n ['😴', 'sleeping zzz', 'smileys'],\n ['🤤', 'drool', 'smileys'],\n ['😷', 'mask sick', 'smileys'],\n ['🤒', 'sick thermometer', 'smileys'],\n ['🤕', 'hurt bandage', 'smileys'],\n ['🤢', 'nausea sick', 'smileys'],\n ['🤮', 'vomit sick', 'smileys'],\n ['🤧', 'sneeze cold', 'smileys'],\n ['🥵', 'hot sweat', 'smileys'],\n ['🥶', 'cold freeze', 'smileys'],\n ['😵', 'dizzy dead', 'smileys'],\n ['🤯', 'mind blown', 'smileys'],\n ['🤠', 'cowboy hat', 'smileys'],\n ['🥳', 'party celebrate', 'smileys'],\n ['😎', 'cool sunglasses', 'smileys'],\n ['🤓', 'nerd glasses', 'smileys'],\n ['🧐', 'monocle curious', 'smileys'],\n ['😕', 'confused', 'smileys'],\n ['😟', 'worried', 'smileys'],\n ['🙁', 'frown sad', 'smileys'],\n ['☹️', 'sad frown', 'smileys'],\n ['😮', 'surprised open mouth', 'smileys'],\n ['😲', 'astonished', 'smileys'],\n ['🥺', 'pleading begging puppy eyes', 'smileys'],\n ['😢', 'cry sad tear', 'smileys'],\n ['😭', 'sob cry loudly', 'smileys'],\n ['😱', 'scream horror fear', 'smileys'],\n ['😡', 'angry red pouting', 'smileys'],\n ['😠', 'angry mad', 'smileys'],\n ['🤬', 'cursing swear', 'smileys'],\n ['😈', 'devil evil smile', 'smileys'],\n ['👿', 'devil angry evil', 'smileys'],\n ['💀', 'skull death', 'smileys'],\n ['☠️', 'skull crossbones', 'smileys'],\n ['💩', 'poop', 'smileys'],\n ['🤡', 'clown', 'smileys'],\n ['👻', 'ghost boo', 'smileys'],\n ['👽', 'alien ufo', 'smileys'],\n ['🤖', 'robot', 'smileys'],\n\n // People & Body\n ['👋', 'wave hello hi hand', 'people'],\n ['🤚', 'raised back hand', 'people'],\n ['✋', 'raised hand stop', 'people'],\n ['🖖', 'vulcan salute spock', 'people'],\n ['👌', 'ok perfect fine', 'people'],\n ['✌️', 'peace victory fingers', 'people'],\n ['🤞', 'fingers crossed luck', 'people'],\n ['🤟', 'love you gesture', 'people'],\n ['🤘', 'sign of horns rock', 'people'],\n ['🤙', 'call me hand', 'people'],\n ['👈', 'point left', 'people'],\n ['👉', 'point right', 'people'],\n ['👆', 'point up', 'people'],\n ['👇', 'point down', 'people'],\n ['☝️', 'index pointing up', 'people'],\n ['👍', 'thumbs up like good', 'people'],\n ['👎', 'thumbs down dislike bad', 'people'],\n ['✊', 'raised fist punch', 'people'],\n ['👊', 'oncoming fist punch', 'people'],\n ['👏', 'clap applause', 'people'],\n ['🙌', 'celebrate raise hands', 'people'],\n ['🤝', 'handshake deal', 'people'],\n ['🙏', 'pray hope please thanks', 'people'],\n ['💅', 'nail polish', 'people'],\n ['💪', 'flexed bicep strong muscle', 'people'],\n ['👀', 'eyes look see', 'people'],\n ['👁️', 'eye', 'people'],\n ['👅', 'tongue', 'people'],\n ['👶', 'baby', 'people'],\n ['🧒', 'child', 'people'],\n ['👦', 'boy', 'people'],\n ['👧', 'girl', 'people'],\n ['🧑', 'person adult', 'people'],\n ['👨', 'man', 'people'],\n ['👩', 'woman', 'people'],\n ['🧔', 'beard man', 'people'],\n ['🧓', 'older person', 'people'],\n ['👴', 'old man', 'people'],\n ['👵', 'old woman', 'people'],\n ['❤️', 'heart love red', 'people'],\n ['🧡', 'orange heart love', 'people'],\n ['💛', 'yellow heart love', 'people'],\n ['💚', 'green heart love', 'people'],\n ['💙', 'blue heart love', 'people'],\n ['💜', 'purple heart love', 'people'],\n ['🖤', 'black heart', 'people'],\n ['🤍', 'white heart', 'people'],\n ['🤎', 'brown heart', 'people'],\n ['💔', 'broken heart', 'people'],\n ['❣️', 'exclamation heart', 'people'],\n ['💕', 'two hearts love', 'people'],\n ['💞', 'revolving hearts', 'people'],\n ['💓', 'beating heart', 'people'],\n ['💗', 'growing heart', 'people'],\n ['💖', 'sparkling heart', 'people'],\n ['💘', 'heart arrow', 'people'],\n ['💝', 'heart ribbon', 'people'],\n ['💬', 'speech bubble comment chat', 'people'],\n ['💭', 'thought bubble', 'people'],\n ['💯', '100 hundred percent perfect', 'people'],\n ['💢', 'anger symbol mad', 'people'],\n ['💤', 'zzz sleep', 'people'],\n\n // Animals & Nature\n ['🐶', 'dog puppy', 'animals'],\n ['🐱', 'cat kitten', 'animals'],\n ['🐭', 'mouse', 'animals'],\n ['🐹', 'hamster', 'animals'],\n ['🐰', 'rabbit bunny', 'animals'],\n ['🦊', 'fox', 'animals'],\n ['🐻', 'bear', 'animals'],\n ['🐼', 'panda', 'animals'],\n ['🐨', 'koala', 'animals'],\n ['🐯', 'tiger', 'animals'],\n ['🦁', 'lion', 'animals'],\n ['🐮', 'cow', 'animals'],\n ['🐷', 'pig', 'animals'],\n ['🐸', 'frog', 'animals'],\n ['🐵', 'monkey', 'animals'],\n ['🙈', 'see no evil monkey', 'animals'],\n ['🙉', 'hear no evil monkey', 'animals'],\n ['🙊', 'speak no evil monkey', 'animals'],\n ['🐔', 'chicken hen', 'animals'],\n ['🐧', 'penguin', 'animals'],\n ['🐦', 'bird', 'animals'],\n ['🦆', 'duck', 'animals'],\n ['🦅', 'eagle', 'animals'],\n ['🦉', 'owl', 'animals'],\n ['🦇', 'bat', 'animals'],\n ['🐺', 'wolf', 'animals'],\n ['🐴', 'horse', 'animals'],\n ['🦄', 'unicorn', 'animals'],\n ['🐝', 'bee', 'animals'],\n ['🦋', 'butterfly', 'animals'],\n ['🐌', 'snail', 'animals'],\n ['🐞', 'ladybug', 'animals'],\n ['🐢', 'turtle', 'animals'],\n ['🐍', 'snake', 'animals'],\n ['🦎', 'lizard', 'animals'],\n ['🐊', 'crocodile', 'animals'],\n ['🐟', 'fish', 'animals'],\n ['🐠', 'tropical fish', 'animals'],\n ['🦈', 'shark', 'animals'],\n ['🐬', 'dolphin', 'animals'],\n ['🐳', 'whale', 'animals'],\n ['🐙', 'octopus', 'animals'],\n ['🦑', 'squid', 'animals'],\n ['🦀', 'crab', 'animals'],\n ['🌸', 'cherry blossom flower', 'animals'],\n ['🌺', 'hibiscus flower', 'animals'],\n ['🌻', 'sunflower', 'animals'],\n ['🌹', 'rose flower', 'animals'],\n ['🌷', 'tulip flower', 'animals'],\n ['🍀', 'four leaf clover luck', 'animals'],\n ['🌿', 'herb leaf green', 'animals'],\n ['🌱', 'seedling sprout', 'animals'],\n ['🌲', 'evergreen tree pine', 'animals'],\n ['🌳', 'deciduous tree', 'animals'],\n ['🌴', 'palm tree', 'animals'],\n ['🍄', 'mushroom', 'animals'],\n ['🌾', 'sheaf wheat', 'animals'],\n ['🐾', 'paw prints animal', 'animals'],\n\n // Food & Drink\n ['🍎', 'apple red', 'food'],\n ['🍊', 'orange tangerine', 'food'],\n ['🍋', 'lemon yellow', 'food'],\n ['🍇', 'grapes', 'food'],\n ['🍓', 'strawberry', 'food'],\n ['🫐', 'blueberry', 'food'],\n ['🍒', 'cherry', 'food'],\n ['🍑', 'peach', 'food'],\n ['🥭', 'mango', 'food'],\n ['🍍', 'pineapple', 'food'],\n ['🥥', 'coconut', 'food'],\n ['🥝', 'kiwi', 'food'],\n ['🍅', 'tomato', 'food'],\n ['🥑', 'avocado', 'food'],\n ['🍆', 'eggplant aubergine', 'food'],\n ['🥕', 'carrot', 'food'],\n ['🌽', 'corn', 'food'],\n ['🥦', 'broccoli', 'food'],\n ['🥬', 'leafy green', 'food'],\n ['🧄', 'garlic', 'food'],\n ['🥜', 'peanut nut', 'food'],\n ['🍞', 'bread loaf', 'food'],\n ['🥐', 'croissant', 'food'],\n ['🧀', 'cheese', 'food'],\n ['🍳', 'egg fry cooking', 'food'],\n ['🥚', 'egg', 'food'],\n ['🥞', 'pancake', 'food'],\n ['🧇', 'waffle', 'food'],\n ['🥓', 'bacon', 'food'],\n ['🥩', 'meat steak', 'food'],\n ['🍗', 'chicken leg', 'food'],\n ['🌭', 'hotdog', 'food'],\n ['🍔', 'burger hamburger', 'food'],\n ['🍟', 'fries french', 'food'],\n ['🍕', 'pizza', 'food'],\n ['🌮', 'taco', 'food'],\n ['🌯', 'burrito wrap', 'food'],\n ['🍜', 'noodles ramen', 'food'],\n ['🍝', 'spaghetti pasta', 'food'],\n ['🍣', 'sushi', 'food'],\n ['🍱', 'bento box', 'food'],\n ['🍦', 'ice cream soft serve', 'food'],\n ['🍩', 'donut', 'food'],\n ['🍪', 'cookie', 'food'],\n ['🎂', 'birthday cake', 'food'],\n ['🍰', 'cake slice', 'food'],\n ['🧁', 'cupcake', 'food'],\n ['🍫', 'chocolate', 'food'],\n ['🍬', 'candy', 'food'],\n ['🍭', 'lollipop', 'food'],\n ['☕', 'coffee hot', 'food'],\n ['🍵', 'tea hot', 'food'],\n ['🧋', 'bubble tea boba', 'food'],\n ['🥤', 'cup straw drink', 'food'],\n ['🍷', 'wine red', 'food'],\n ['🍸', 'cocktail martini', 'food'],\n ['🍺', 'beer mug', 'food'],\n ['🍻', 'clinking beer mugs', 'food'],\n ['🥂', 'champagne toast celebrate', 'food'],\n ['🧃', 'juice box', 'food'],\n ['🧊', 'ice cube', 'food'],\n\n // Travel & Places\n ['🚀', 'rocket space', 'travel'],\n ['🛸', 'ufo flying saucer', 'travel'],\n ['✈️', 'airplane plane fly', 'travel'],\n ['🚁', 'helicopter', 'travel'],\n ['🚂', 'train locomotive', 'travel'],\n ['🚄', 'bullet train fast', 'travel'],\n ['🚇', 'subway metro', 'travel'],\n ['🚌', 'bus', 'travel'],\n ['🚑', 'ambulance', 'travel'],\n ['🚒', 'fire truck', 'travel'],\n ['🚓', 'police car', 'travel'],\n ['🚕', 'taxi cab', 'travel'],\n ['🚗', 'car automobile red', 'travel'],\n ['🚙', 'suv car', 'travel'],\n ['🚚', 'truck delivery', 'travel'],\n ['🚜', 'tractor farm', 'travel'],\n ['🏎️', 'racing car fast', 'travel'],\n ['🏍️', 'motorcycle', 'travel'],\n ['🚲', 'bicycle bike', 'travel'],\n ['🛴', 'scooter kick', 'travel'],\n ['⛵', 'sailboat boat', 'travel'],\n ['🚢', 'ship cruise', 'travel'],\n ['🏠', 'house home', 'travel'],\n ['🏢', 'office building', 'travel'],\n ['🏥', 'hospital', 'travel'],\n ['🏦', 'bank', 'travel'],\n ['🏪', 'store shop convenience', 'travel'],\n ['🏫', 'school', 'travel'],\n ['🏰', 'castle european', 'travel'],\n ['🏯', 'japanese castle', 'travel'],\n ['🗼', 'tokyo tower', 'travel'],\n ['🗽', 'statue liberty new york', 'travel'],\n ['⛪', 'church', 'travel'],\n ['🕌', 'mosque', 'travel'],\n ['⛩️', 'shinto shrine', 'travel'],\n ['⛲', 'fountain', 'travel'],\n ['⛺', 'tent camping', 'travel'],\n ['🌁', 'fog foggy bridge', 'travel'],\n ['🌃', 'night city stars', 'travel'],\n ['🏙️', 'cityscape city buildings', 'travel'],\n ['🌅', 'sunrise morning', 'travel'],\n ['🌈', 'rainbow colorful', 'travel'],\n ['⛰️', 'mountain', 'travel'],\n ['🏔️', 'snow mountain', 'travel'],\n ['🗻', 'mount fuji', 'travel'],\n ['🏕️', 'camping tent', 'travel'],\n ['🗺️', 'world map', 'travel'],\n ['🧭', 'compass navigation', 'travel'],\n ['🌍', 'earth europe africa globe', 'travel'],\n ['🌎', 'earth americas globe', 'travel'],\n ['🌏', 'earth asia globe', 'travel'],\n ['🌐', 'globe internet web', 'travel'],\n\n // Objects\n ['💎', 'diamond gem jewel', 'objects'],\n ['💍', 'ring engagement', 'objects'],\n ['👑', 'crown royal king queen', 'objects'],\n ['🎩', 'top hat magic', 'objects'],\n ['💼', 'briefcase work business', 'objects'],\n ['👜', 'handbag purse', 'objects'],\n ['🎒', 'backpack bag school', 'objects'],\n ['👓', 'glasses eyewear', 'objects'],\n ['🕶️', 'sunglasses cool', 'objects'],\n ['💡', 'light bulb idea', 'objects'],\n ['🔦', 'flashlight torch', 'objects'],\n ['🕯️', 'candle light', 'objects'],\n ['🔋', 'battery charge', 'objects'],\n ['💻', 'laptop computer', 'objects'],\n ['🖥️', 'desktop monitor computer', 'objects'],\n ['📱', 'phone mobile cell', 'objects'],\n ['⌨️', 'keyboard type', 'objects'],\n ['🖱️', 'mouse computer click', 'objects'],\n ['📺', 'television tv', 'objects'],\n ['📷', 'camera photo', 'objects'],\n ['📹', 'video camera', 'objects'],\n ['🎥', 'movie camera film', 'objects'],\n ['☎️', 'telephone phone', 'objects'],\n ['⏰', 'alarm clock wake', 'objects'],\n ['⌚', 'watch time', 'objects'],\n ['🔑', 'key', 'objects'],\n ['🗝️', 'old key', 'objects'],\n ['🔒', 'lock closed', 'objects'],\n ['🔓', 'unlock open', 'objects'],\n ['🔨', 'hammer tool', 'objects'],\n ['🔧', 'wrench tool', 'objects'],\n ['🔩', 'bolt nut', 'objects'],\n ['⚙️', 'gear setting', 'objects'],\n ['🧲', 'magnet attract', 'objects'],\n ['📚', 'books stack library', 'objects'],\n ['📖', 'book open read', 'objects'],\n ['📝', 'memo write note', 'objects'],\n ['✏️', 'pencil write edit', 'objects'],\n ['📌', 'pushpin tack', 'objects'],\n ['📎', 'paperclip attach', 'objects'],\n ['📊', 'bar chart graph', 'objects'],\n ['📈', 'chart up growth trend', 'objects'],\n ['📉', 'chart down loss decline', 'objects'],\n ['📅', 'calendar date', 'objects'],\n ['📦', 'package box', 'objects'],\n ['📫', 'mailbox closed', 'objects'],\n ['📧', 'email envelope', 'objects'],\n ['🎁', 'gift present', 'objects'],\n ['🎀', 'ribbon bow', 'objects'],\n ['🎉', 'party celebrate confetti', 'objects'],\n ['🎊', 'confetti celebrate', 'objects'],\n ['🔮', 'crystal ball magic fortune', 'objects'],\n ['🪄', 'magic wand', 'objects'],\n ['🎯', 'target bullseye dart', 'objects'],\n ['🎲', 'dice game board', 'objects'],\n ['🎮', 'video game controller', 'objects'],\n ['🎭', 'theater masks drama', 'objects'],\n ['🎨', 'art palette paint', 'objects'],\n ['🎬', 'clapper film movie', 'objects'],\n ['🎤', 'microphone sing karaoke', 'objects'],\n ['🎧', 'headphones music listen', 'objects'],\n ['🎵', 'music note', 'objects'],\n ['🎶', 'music notes', 'objects'],\n ['🎸', 'guitar electric', 'objects'],\n ['🎹', 'piano keyboard music', 'objects'],\n ['🥁', 'drum percussion', 'objects'],\n ['🎷', 'saxophone jazz', 'objects'],\n ['🎺', 'trumpet', 'objects'],\n ['🎻', 'violin', 'objects'],\n ['⚽', 'soccer ball football', 'objects'],\n ['🏀', 'basketball', 'objects'],\n ['🏈', 'american football', 'objects'],\n ['⚾', 'baseball', 'objects'],\n ['🎾', 'tennis', 'objects'],\n ['🏐', 'volleyball', 'objects'],\n ['🏆', 'trophy winner award', 'objects'],\n ['🥇', 'gold medal first', 'objects'],\n ['🏅', 'sports medal', 'objects'],\n\n // Symbols\n ['✅', 'check green done success', 'symbols'],\n ['❌', 'cross x no cancel', 'symbols'],\n ['⭕', 'circle red', 'symbols'],\n ['⛔', 'no entry stop', 'symbols'],\n ['🚫', 'prohibited no banned', 'symbols'],\n ['⚠️', 'warning caution danger', 'symbols'],\n ['❗', 'exclamation red important', 'symbols'],\n ['❓', 'question mark', 'symbols'],\n ['‼️', 'double exclamation', 'symbols'],\n ['💯', '100 hundred percent perfect', 'symbols'],\n ['🔴', 'red circle dot', 'symbols'],\n ['🟠', 'orange circle', 'symbols'],\n ['🟡', 'yellow circle', 'symbols'],\n ['🟢', 'green circle', 'symbols'],\n ['🔵', 'blue circle', 'symbols'],\n ['🟣', 'purple circle', 'symbols'],\n ['⚫', 'black circle', 'symbols'],\n ['⚪', 'white circle', 'symbols'],\n ['🟤', 'brown circle', 'symbols'],\n ['🔺', 'red triangle up', 'symbols'],\n ['🔻', 'red triangle down', 'symbols'],\n ['🔷', 'blue diamond large', 'symbols'],\n ['🔶', 'orange diamond large', 'symbols'],\n ['🔹', 'blue diamond small', 'symbols'],\n ['🔸', 'orange diamond small', 'symbols'],\n ['⭐', 'star yellow', 'symbols'],\n ['🌟', 'glowing star shine', 'symbols'],\n ['✨', 'sparkles shine', 'symbols'],\n ['💫', 'dizzy star spin', 'symbols'],\n ['⚡', 'lightning bolt energy power', 'symbols'],\n ['🔥', 'fire hot flame', 'symbols'],\n ['💥', 'explosion boom', 'symbols'],\n ['❄️', 'snowflake cold ice winter', 'symbols'],\n ['🌊', 'wave water ocean sea', 'symbols'],\n ['💨', 'wind blow dash', 'symbols'],\n ['🌀', 'cyclone tornado spiral', 'symbols'],\n ['♻️', 'recycle loop green', 'symbols'],\n ['✔️', 'check tick done', 'symbols'],\n ['➕', 'plus add', 'symbols'],\n ['➖', 'minus subtract', 'symbols'],\n ['➗', 'divide division', 'symbols'],\n ['✖️', 'multiply times cross', 'symbols'],\n ['▶️', 'play button right', 'symbols'],\n ['⏸️', 'pause', 'symbols'],\n ['⏹️', 'stop square', 'symbols'],\n ['⏩', 'fast forward', 'symbols'],\n ['⏪', 'rewind fast backward', 'symbols'],\n ['🔔', 'bell notification', 'symbols'],\n ['🔕', 'bell slash mute', 'symbols'],\n ['🔊', 'speaker volume high', 'symbols'],\n ['🔇', 'mute silent no sound', 'symbols'],\n ['📢', 'loudspeaker announcement', 'symbols'],\n ['📣', 'megaphone cheer', 'symbols'],\n ['🏳️', 'white flag', 'symbols'],\n ['🏴', 'black flag', 'symbols'],\n ['🚩', 'red flag', 'symbols'],\n ['🏁', 'checkered flag finish race', 'symbols'],\n ['🆕', 'new badge', 'symbols'],\n ['🆓', 'free badge', 'symbols'],\n ['🆒', 'cool badge', 'symbols'],\n ['🔝', 'top arrow', 'symbols'],\n ['🔙', 'back arrow', 'symbols'],\n ['ℹ️', 'information info', 'symbols'],\n ['📍', 'pin location map', 'symbols'],\n ['🔗', 'link chain', 'symbols'],\n ['©️', 'copyright', 'symbols'],\n ['®️', 'registered trademark', 'symbols'],\n ['™️', 'trademark', 'symbols'],\n ['#️⃣', 'hash number', 'symbols'],\n ['0️⃣', 'zero number', 'symbols'],\n ['1️⃣', 'one number', 'symbols'],\n ['2️⃣', 'two number', 'symbols'],\n ['3️⃣', 'three number', 'symbols'],\n ['4️⃣', 'four number', 'symbols'],\n ['5️⃣', 'five number', 'symbols'],\n];\n\n// ---------------------------------------------------------------------------\n// Dialog class\n// ---------------------------------------------------------------------------\n\nexport class EmojiDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n this._activeCat = 'all';\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n // Dialog grid is built lazily on first show() to avoid rendering ~500 DOM nodes at load time.\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n if (!this._dialog) {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._activeCat = 'all';\n this._searchInput.value = '';\n this._updateCatTabs();\n this._filterEmojis('', 'all');\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.emojiDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box an-emoji-box' });\n\n // Title row\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '×';\n titleRow.append(title, closeBtn);\n\n // Search\n const searchInput = createElement('input', {\n type: 'search',\n class: 'an-input an-icon-search',\n placeholder: L.searchPlaceholder,\n autocomplete: 'off',\n });\n this._searchInput = searchInput;\n\n // Category tabs\n const catBar = createElement('div', { class: 'an-icon-cats' });\n const allTab = createElement('button', { type: 'button', class: 'an-icon-cat active', 'data-cat': 'all' });\n allTab.textContent = L.all;\n catBar.appendChild(allTab);\n EMOJI_CATS.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = (L.categories && L.categories[id]) || label;\n catBar.appendChild(tab);\n });\n this._catBar = catBar;\n\n // Emoji grid — one button per emoji, click = immediate insert\n const grid = createElement('div', { class: 'an-emoji-grid' });\n EMOJI_LIST.forEach(([char, keywords, cat]) => {\n const cell = createElement('button', {\n type: 'button',\n class: 'an-emoji-cell',\n 'data-char': char,\n 'data-keywords': keywords,\n 'data-cat': cat,\n title: keywords.split(' ').slice(0, 2).join(' '),\n });\n cell.textContent = char;\n grid.appendChild(cell);\n });\n this._grid = grid;\n\n // Cancel only — clicking an emoji inserts immediately\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(cancelBtn);\n\n box.append(titleRow, searchInput, catBar, grid, btnRow);\n overlay.appendChild(box);\n\n // Events\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(searchInput, 'input', () => this._filterEmojis(searchInput.value, this._activeCat));\n const d5 = on(catBar, 'click', (e) => {\n const tab = e.target.closest('[data-cat]');\n if (tab) {\n this._activeCat = tab.dataset.cat;\n this._updateCatTabs();\n this._filterEmojis(this._searchInput.value, this._activeCat);\n }\n });\n const d6 = on(grid, 'click', (e) => {\n const cell = e.target.closest('.an-emoji-cell');\n if (cell) this._onEmojiClick(cell.dataset.char);\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6);\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Filter\n // ---------------------------------------------------------------------------\n\n _updateCatTabs() {\n this._catBar.querySelectorAll('.an-icon-cat').forEach((tab) => {\n tab.classList.toggle('active', tab.dataset.cat === this._activeCat);\n });\n }\n\n _filterEmojis(query, cat) {\n const q = (query || '').trim().toLowerCase();\n let count = 0;\n this._grid.querySelectorAll('.an-emoji-cell').forEach((cell) => {\n const matchCat = !cat || cat === 'all' || cell.dataset.cat === cat;\n const matchQuery = !q || cell.dataset.keywords.includes(q) || cell.dataset.char === q;\n const visible = matchCat && matchQuery;\n cell.style.display = visible ? '' : 'none';\n if (visible) count++;\n });\n let empty = this._grid.querySelector('.an-icon-empty');\n if (!empty) {\n empty = createElement('div', { class: 'an-icon-empty' });\n empty.textContent = 'No emojis found';\n this._grid.appendChild(empty);\n }\n empty.style.display = count > 0 ? 'none' : '';\n }\n\n // ---------------------------------------------------------------------------\n // Insert\n // ---------------------------------------------------------------------------\n\n _onEmojiClick(char) {\n const savedRange = this._savedRange;\n const editable = this.context.layoutInfo.editable;\n\n // 1. Restore selection while dialog is still mounted (same pattern as ImageDialog)\n if (savedRange) savedRange.select();\n\n const sel = window.getSelection();\n let range = sel && sel.rangeCount > 0 ? sel.getRangeAt(0) : null;\n if (!range) {\n range = document.createRange();\n range.selectNodeContents(editable);\n range.collapse(false);\n }\n\n // 2. Insert emoji as a plain text node — no ZWS or execCommand needed.\n // Text nodes are natively navigable so the caret lands cleanly after.\n //\n // E-1: When the range covers the entire content of a <td>/<th>,\n // deleteContents() can drift the range endpoint outside the cell in some\n // browsers. Save the cell reference first and re-anchor after deletion.\n const _sc = range.startContainer;\n const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest?.('td, th');\n range.deleteContents();\n if (_tdAnchor && _tdAnchor.isConnected && !_tdAnchor.contains(range.startContainer)) {\n range.setStart(_tdAnchor, 0);\n range.collapse(true);\n }\n const textNode = document.createTextNode(char);\n range.insertNode(textNode);\n\n // 3. Place caret immediately after the emoji character\n range.setStartAfter(textNode);\n range.collapse(true);\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n // 4. Close and restore editor focus\n this._close();\n editable.focus();\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Open / Close\n // ---------------------------------------------------------------------------\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._searchInput && this._searchInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n}\n","/**\n * IconDialog.js - Browse and insert FontAwesome Free icons\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// Icon catalogue — FA 6 Free Solid slug names, grouped by category\n// ---------------------------------------------------------------------------\n\nconst ICON_CATEGORIES = [\n { id: 'popular', label: 'Popular' },\n { id: 'interface', label: 'Interface' },\n { id: 'navigation', label: 'Navigation' },\n { id: 'media', label: 'Media' },\n { id: 'communication', label: 'Communication' },\n { id: 'files', label: 'Files' },\n { id: 'people', label: 'People' },\n { id: 'objects', label: 'Objects' },\n];\n\n// Each entry: [slug, category]\nconst ICON_LIST = [\n // Popular\n ['house', 'popular'],\n ['star', 'popular'],\n ['heart', 'popular'],\n ['check', 'popular'],\n ['xmark', 'popular'],\n ['plus', 'popular'],\n ['minus', 'popular'],\n ['magnifying-glass', 'popular'],\n ['gear', 'popular'],\n ['bell', 'popular'],\n ['user', 'popular'],\n ['envelope', 'popular'],\n ['phone', 'popular'],\n ['calendar', 'popular'],\n ['clock', 'popular'],\n ['lock', 'popular'],\n ['eye', 'popular'],\n ['eye-slash', 'popular'],\n ['trash', 'popular'],\n ['pen', 'popular'],\n ['bookmark', 'popular'],\n ['flag', 'popular'],\n ['thumbs-up', 'popular'],\n ['thumbs-down', 'popular'],\n ['circle-info', 'popular'],\n ['triangle-exclamation', 'popular'],\n ['circle-check', 'popular'],\n ['circle-xmark', 'popular'],\n ['share', 'popular'],\n ['download', 'popular'],\n ['upload', 'popular'],\n ['tag', 'popular'],\n // Interface\n ['bars', 'interface'],\n ['ellipsis', 'interface'],\n ['ellipsis-vertical', 'interface'],\n ['list', 'interface'],\n ['table-cells', 'interface'],\n ['table-list', 'interface'],\n ['grip', 'interface'],\n ['filter', 'interface'],\n ['sort', 'interface'],\n ['arrows-rotate', 'interface'],\n ['rotate', 'interface'],\n ['rotate-left', 'interface'],\n ['rotate-right', 'interface'],\n ['copy', 'interface'],\n ['floppy-disk', 'interface'],\n ['print', 'interface'],\n ['link', 'interface'],\n ['code', 'interface'],\n ['expand', 'interface'],\n ['compress', 'interface'],\n ['cloud', 'interface'],\n ['lock-open', 'interface'],\n ['key', 'interface'],\n ['shield', 'interface'],\n ['shield-halved', 'interface'],\n ['sliders', 'interface'],\n ['toggle-on', 'interface'],\n ['square-check', 'interface'],\n ['circle-plus', 'interface'],\n ['circle-minus', 'interface'],\n // Navigation\n ['arrow-right', 'navigation'],\n ['arrow-left', 'navigation'],\n ['arrow-up', 'navigation'],\n ['arrow-down', 'navigation'],\n ['chevron-right', 'navigation'],\n ['chevron-left', 'navigation'],\n ['chevron-up', 'navigation'],\n ['chevron-down', 'navigation'],\n ['angle-right', 'navigation'],\n ['angle-left', 'navigation'],\n ['angle-up', 'navigation'],\n ['angle-down', 'navigation'],\n ['angles-right', 'navigation'],\n ['angles-left', 'navigation'],\n ['location-dot', 'navigation'],\n ['compass', 'navigation'],\n ['map', 'navigation'],\n ['map-pin', 'navigation'],\n ['route', 'navigation'],\n ['circle-arrow-right', 'navigation'],\n ['circle-arrow-left', 'navigation'],\n ['arrow-trend-up', 'navigation'],\n ['arrow-trend-down', 'navigation'],\n ['right-from-bracket', 'navigation'],\n ['right-to-bracket', 'navigation'],\n // Media\n ['play', 'media'],\n ['pause', 'media'],\n ['stop', 'media'],\n ['forward', 'media'],\n ['backward', 'media'],\n ['forward-step', 'media'],\n ['backward-step', 'media'],\n ['volume-high', 'media'],\n ['volume-low', 'media'],\n ['volume-xmark', 'media'],\n ['volume-off', 'media'],\n ['music', 'media'],\n ['headphones', 'media'],\n ['microphone', 'media'],\n ['microphone-slash', 'media'],\n ['film', 'media'],\n ['camera', 'media'],\n ['camera-rotate', 'media'],\n ['video', 'media'],\n ['image', 'media'],\n ['images', 'media'],\n ['photo-film', 'media'],\n ['podcast', 'media'],\n ['radio', 'media'],\n // Communication\n ['comment', 'communication'],\n ['comments', 'communication'],\n ['comment-dots', 'communication'],\n ['message', 'communication'],\n ['paper-plane', 'communication'],\n ['reply', 'communication'],\n ['reply-all', 'communication'],\n ['at', 'communication'],\n ['hashtag', 'communication'],\n ['wifi', 'communication'],\n ['signal', 'communication'],\n ['rss', 'communication'],\n ['share-nodes', 'communication'],\n ['inbox', 'communication'],\n ['phone-volume', 'communication'],\n ['mobile', 'communication'],\n ['mobile-screen', 'communication'],\n ['laptop', 'communication'],\n ['desktop', 'communication'],\n ['tower-broadcast', 'communication'],\n // Files\n ['file', 'files'],\n ['file-lines', 'files'],\n ['folder', 'files'],\n ['folder-open', 'files'],\n ['folder-plus', 'files'],\n ['folder-minus', 'files'],\n ['file-image', 'files'],\n ['file-pdf', 'files'],\n ['file-code', 'files'],\n ['file-zipper', 'files'],\n ['file-audio', 'files'],\n ['file-video', 'files'],\n ['file-arrow-up', 'files'],\n ['file-arrow-down', 'files'],\n ['database', 'files'],\n ['box', 'files'],\n ['box-open', 'files'],\n ['hard-drive', 'files'],\n ['server', 'files'],\n // People\n ['user', 'people'],\n ['users', 'people'],\n ['user-group', 'people'],\n ['user-plus', 'people'],\n ['user-minus', 'people'],\n ['user-check', 'people'],\n ['user-xmark', 'people'],\n ['user-tie', 'people'],\n ['user-shield', 'people'],\n ['user-secret', 'people'],\n ['person', 'people'],\n ['person-running', 'people'],\n ['person-walking', 'people'],\n ['child', 'people'],\n ['handshake', 'people'],\n ['hand', 'people'],\n ['hands-holding', 'people'],\n ['people-group', 'people'],\n // Objects\n ['pencil', 'objects'],\n ['paintbrush', 'objects'],\n ['eraser', 'objects'],\n ['scissors', 'objects'],\n ['wrench', 'objects'],\n ['screwdriver', 'objects'],\n ['hammer', 'objects'],\n ['toolbox', 'objects'],\n ['graduation-cap', 'objects'],\n ['book', 'objects'],\n ['book-open', 'objects'],\n ['glasses', 'objects'],\n ['microscope', 'objects'],\n ['flask', 'objects'],\n ['stethoscope', 'objects'],\n ['hospital', 'objects'],\n ['building', 'objects'],\n ['city', 'objects'],\n ['car', 'objects'],\n ['truck', 'objects'],\n ['plane', 'objects'],\n ['train', 'objects'],\n ['bicycle', 'objects'],\n ['bus', 'objects'],\n ['rocket', 'objects'],\n ['briefcase', 'objects'],\n ['cart-shopping', 'objects'],\n ['bag-shopping', 'objects'],\n ['credit-card', 'objects'],\n ['money-bill', 'objects'],\n ['chart-bar', 'objects'],\n ['chart-line', 'objects'],\n ['chart-pie', 'objects'],\n ['bolt', 'objects'],\n ['sun', 'objects'],\n ['moon', 'objects'],\n ['snowflake', 'objects'],\n ['fire', 'objects'],\n ['droplet', 'objects'],\n ['leaf', 'objects'],\n ['tree', 'objects'],\n ['earth-americas', 'objects'],\n ['globe', 'objects'],\n ['award', 'objects'],\n ['trophy', 'objects'],\n ['gift', 'objects'],\n ['puzzle-piece', 'objects'],\n];\n\nexport class IconDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n this._selectedIcon = null;\n this._activeCat = 'all';\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._ensureFontAwesome();\n // Dialog grid is built lazily on first show() to avoid rendering ~250 icon cells at load time.\n return this;\n }\n\n /**\n * Injects FA 6 Free CSS from CDN if it is not already on the page.\n * This guarantees icon glyphs render in the grid, preview, and in the\n * editor content after insertion — regardless of whether the host page\n * loaded FA itself.\n */\n _ensureFontAwesome() {\n // Already present (icon element or stylesheet link)?\n if (document.getElementById('an-fontawesome-css')) return;\n const links = Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]'))\n .map((l) => l.href || '').join(' ');\n if (/fontawesome|font-awesome/.test(links)) return;\n if (document.querySelector('.fa-solid, .fas, .far, .fab')) return;\n\n const link = document.createElement('link');\n link.id = 'an-fontawesome-css';\n link.rel = 'stylesheet';\n link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css';\n link.crossOrigin = 'anonymous';\n link.referrerPolicy = 'no-referrer';\n document.head.appendChild(link);\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n if (!this._dialog) {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._selectedIcon = null;\n this._activeCat = 'all';\n this._searchInput.value = '';\n // Clear previously selected icon highlight and disable Insert button\n this._grid.querySelectorAll('.an-icon-cell.active').forEach((c) => c.classList.remove('active'));\n this._insertBtn.setAttribute('disabled', '');\n this._updateCatTabs();\n this._filterIcons('', 'all');\n this._updatePreview(null);\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.iconDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n\n const box = createElement('div', { class: 'an-dialog-box an-icon-box' });\n\n // Title row\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '×';\n titleRow.append(title, closeBtn);\n\n // Search\n const searchInput = createElement('input', {\n type: 'search',\n class: 'an-input an-icon-search',\n placeholder: L.searchPlaceholder,\n autocomplete: 'off',\n });\n this._searchInput = searchInput;\n\n // Category tabs\n const catBar = createElement('div', { class: 'an-icon-cats' });\n const allTab = createElement('button', { type: 'button', class: 'an-icon-cat active', 'data-cat': 'all' });\n allTab.textContent = L.all;\n catBar.appendChild(allTab);\n ICON_CATEGORIES.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = (L.categories && L.categories[id]) || label;\n catBar.appendChild(tab);\n });\n this._catBar = catBar;\n\n // Icon grid\n const grid = createElement('div', { class: 'an-icon-grid' });\n ICON_LIST.forEach(([name, cat]) => {\n const cell = createElement('button', { type: 'button', class: 'an-icon-cell', 'data-name': name, 'data-cat': cat, title: name });\n const icon = createElement('i', { class: 'fa-solid fa-' + name, 'aria-hidden': 'true' });\n const label = createElement('span');\n label.textContent = name;\n cell.append(icon, label);\n grid.appendChild(cell);\n });\n this._grid = grid;\n\n // Options row: style + size + color\n const optRow = createElement('div', { class: 'an-icon-options' });\n\n const styleLabel = createElement('label', { class: 'an-label' });\n styleLabel.textContent = L.style;\n const styleSelect = createElement('select', { class: 'an-input an-icon-option-select' });\n [['fa-solid', 'Solid'], ['fa-regular', 'Regular'], ['fa-light', 'Light (Pro)']].forEach(([v, t]) => {\n const opt = createElement('option', { value: v });\n opt.textContent = t;\n styleSelect.appendChild(opt);\n });\n styleSelect.value = 'fa-solid';\n this._styleSelect = styleSelect;\n\n const sizeLabel = createElement('label', { class: 'an-label' });\n sizeLabel.textContent = L.size;\n const sizeSelect = createElement('select', { class: 'an-input an-icon-option-select' });\n [['', 'Inherit'], ['0.75em', '0.75em'], ['1em', '1em'], ['1.25em', '1.25em'], ['1.5em', '1.5em'], ['2em', '2em'], ['3em', '3em']].forEach(([v, t]) => {\n const opt = createElement('option', { value: v });\n if (v === '1em') opt.selected = true;\n opt.textContent = t;\n sizeSelect.appendChild(opt);\n });\n this._sizeSelect = sizeSelect;\n\n const colorLabel = createElement('label', { class: 'an-label' });\n colorLabel.textContent = L.color;\n const colorInput = createElement('input', { type: 'color', class: 'an-icon-color', value: '#000000' });\n this._colorInput = colorInput;\n\n const useColorLabel = createElement('label', { class: 'an-label an-label-inline an-icon-use-color' });\n const useColorCb = createElement('input', { type: 'checkbox', checked: '' });\n this._useColorCb = useColorCb;\n useColorLabel.append(useColorCb, document.createTextNode(L.useColor));\n\n optRow.append(styleLabel, styleSelect, sizeLabel, sizeSelect, colorLabel, colorInput, useColorLabel);\n\n // Preview\n const preview = createElement('div', { class: 'an-icon-preview' });\n const previewHint = createElement('span', { class: 'an-icon-preview-hint' });\n previewHint.textContent = L.selectHint;\n preview.appendChild(previewHint);\n this._preview = preview;\n\n // Actions\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary', disabled: '' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.append(insertBtn, cancelBtn);\n this._insertBtn = insertBtn;\n\n box.append(titleRow, searchInput, catBar, grid, optRow, preview, btnRow);\n overlay.appendChild(box);\n\n // -------------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------------\n\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(insertBtn, 'click', () => this._onInsert());\n const d4 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d5 = on(searchInput, 'input', () => this._filterIcons(searchInput.value, this._activeCat));\n const d6 = on(catBar, 'click', (e) => {\n const tab = e.target.closest('[data-cat]');\n if (tab) {\n this._activeCat = tab.dataset.cat;\n this._updateCatTabs();\n this._filterIcons(this._searchInput.value, this._activeCat);\n }\n });\n const d7 = on(grid, 'click', (e) => {\n const cell = e.target.closest('.an-icon-cell');\n if (cell) this._selectIcon(cell.dataset.name);\n });\n const d8 = on(styleSelect, 'change', () => this._updatePreview(this._selectedIcon));\n const d9 = on(sizeSelect, 'change', () => this._updatePreview(this._selectedIcon));\n const d10 = on(colorInput, 'input', () => this._updatePreview(this._selectedIcon));\n const d11 = on(useColorCb, 'change', () => this._updatePreview(this._selectedIcon));\n\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Filter / select\n // ---------------------------------------------------------------------------\n\n _updateCatTabs() {\n this._catBar.querySelectorAll('.an-icon-cat').forEach((tab) => {\n tab.classList.toggle('active', tab.dataset.cat === this._activeCat);\n });\n }\n\n _filterIcons(query, cat) {\n const q = (query || '').trim().toLowerCase();\n let visibleCount = 0;\n this._grid.querySelectorAll('.an-icon-cell').forEach((cell) => {\n const name = cell.dataset.name;\n const cellCat = cell.dataset.cat;\n const matchesCat = !cat || cat === 'all' || cellCat === cat;\n const matchesQuery = !q || name.includes(q);\n const visible = matchesCat && matchesQuery;\n cell.style.display = visible ? '' : 'none';\n if (visible) visibleCount++;\n });\n // Show empty state if needed\n let empty = this._grid.querySelector('.an-icon-empty');\n if (!empty) {\n empty = createElement('div', { class: 'an-icon-empty' });\n empty.textContent = 'No icons found';\n this._grid.appendChild(empty);\n }\n empty.style.display = visibleCount > 0 ? 'none' : '';\n }\n\n _selectIcon(name) {\n this._selectedIcon = name;\n // Highlight selected cell\n this._grid.querySelectorAll('.an-icon-cell').forEach((cell) => {\n cell.classList.toggle('active', cell.dataset.name === name);\n });\n // Enable insert button\n this._insertBtn.removeAttribute('disabled');\n // Update preview\n this._updatePreview(name);\n }\n\n _updatePreview(name) {\n if (!this._preview) return;\n if (!name) {\n this._preview.innerHTML = '<span class=\"an-icon-preview-hint\">Select an icon</span>';\n return;\n }\n const cls = (this._styleSelect && this._styleSelect.value) || 'fa-solid';\n const size = (this._sizeSelect && this._sizeSelect.value) || '1em';\n const useColor = this._useColorCb ? this._useColorCb.checked : false;\n const color = (useColor && this._colorInput) ? this._colorInput.value : '';\n const styleAttr = [\n size ? `font-size:${size}` : '',\n color ? `color:${color}` : '',\n ].filter(Boolean).join(';');\n // Use innerHTML — atomic, no partial-update risk\n this._preview.innerHTML =\n `<i class=\"${cls} fa-${name}\" aria-hidden=\"true\"${\n styleAttr ? ` style=\"${styleAttr}\"` : ''\n }></i>` +\n `<div class=\"an-icon-preview-name\">${cls} fa-${name}</div>`;\n }\n\n // ---------------------------------------------------------------------------\n // Insert\n // ---------------------------------------------------------------------------\n\n _onInsert() {\n if (!this._selectedIcon) return;\n\n const cls = (this._styleSelect && this._styleSelect.value) || 'fa-solid';\n const size = (this._sizeSelect && this._sizeSelect.value) || '';\n const useColor = this._useColorCb ? this._useColorCb.checked : false;\n const color = (useColor && this._colorInput) ? this._colorInput.value : '';\n const styleParts = [\n size ? `font-size:${size}` : '',\n color ? `color:${color}` : '',\n ].filter(Boolean);\n\n const iconEl = document.createElement('i');\n iconEl.className = `${cls} fa-${this._selectedIcon}`;\n iconEl.setAttribute('aria-hidden', 'true');\n iconEl.setAttribute('contenteditable', 'false');\n if (styleParts.length) iconEl.setAttribute('style', styleParts.join(';'));\n\n const savedRange = this._savedRange;\n const editable = this.context.layoutInfo.editable;\n\n // ---- Same ordering as ImageDialog (the proven pattern) ----\n // 1. Restore the selection while the dialog is still mounted\n if (savedRange) savedRange.select();\n\n // 2. Get the now-live range from the selection\n const sel = window.getSelection();\n let range = sel && sel.rangeCount > 0 ? sel.getRangeAt(0) : null;\n if (!range) {\n range = document.createRange();\n range.selectNodeContents(editable);\n range.collapse(false);\n }\n\n // 3. Insert the <i> node directly — never via execCommand/insertHTML\n // (execCommand leaves the caret inside the inserted element)\n //\n // E-1: When the range covers the entire content of a <td>/<th>,\n // deleteContents() can drift the range endpoint outside the cell in some\n // browsers. Save the cell reference first and re-anchor after deletion.\n const _sc = range.startContainer;\n const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest?.('td, th');\n range.deleteContents();\n if (_tdAnchor && _tdAnchor.isConnected && !_tdAnchor.contains(range.startContainer)) {\n range.setStart(_tdAnchor, 0);\n range.collapse(true);\n }\n range.insertNode(iconEl);\n\n // 4. Place cursor after the icon.\n // Keep a text anchor (\\u200B) after the icon so ArrowLeft/ArrowRight and\n // caret placement at end-of-line stay stable across browsers.\n let caretTextNode = iconEl.nextSibling;\n if (!caretTextNode || caretTextNode.nodeType !== Node.TEXT_NODE) {\n caretTextNode = document.createTextNode('\\u200B');\n iconEl.parentNode.insertBefore(caretTextNode, iconEl.nextSibling);\n } else if (!caretTextNode.textContent) {\n // Split text-node insertions can leave an empty text node after icon.\n // Fill it with ZWS so caret-after-icon remains stable at end-of-line.\n caretTextNode.textContent = '\\u200B';\n }\n\n const caretOffset = ((caretTextNode.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n const caretRange = document.createRange();\n caretRange.setStart(caretTextNode, Math.min(caretOffset, caretTextNode.textContent.length));\n caretRange.collapse(true);\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(caretRange);\n }\n\n // 5. Close dialog last — same as ImageDialog\n this._close();\n\n // 6. Restore editor focus (needed for toolbar refresh via afterCommand)\n editable.focus();\n if (sel) {\n // Some browsers reset selection when refocusing editable after closing dialog.\n sel.removeAllRanges();\n sel.addRange(caretRange);\n }\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Open / Close\n // ---------------------------------------------------------------------------\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._searchInput && this._searchInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n this._selectedIcon = null;\n }\n}\n","// ContextMenu.js - Right-click context menu for editor actions\nimport { createElement, on } from '../core/dom.js';\nimport { sanitiseHTML } from '../core/sanitise.js';\n\n// SVG icon map — 16×16 Heroicons-style paths\nconst ICONS = {\n undo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/></svg>`,\n redo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/></svg>`,\n cut: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"6\" cy=\"20\" r=\"3\"/><circle cx=\"6\" cy=\"4\" r=\"3\"/><line x1=\"19\" y1=\"5\" x2=\"6\" y2=\"19\"/><line x1=\"19\" y1=\"19\" x2=\"13.5\" y2=\"13.5\"/></svg>`,\n copy: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`,\n paste: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\"/></svg>`,\n bold: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/></svg>`,\n italic: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/></svg>`,\n underline: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/></svg>`,\n link: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`,\n image: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>`,\n video: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"23 7 16 12 23 17 23 7\"/><rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\"/></svg>`,\n // Image format operations\n floatLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"6\" x2=\"22\" y2=\"6\"/><line x1=\"12\" y1=\"9\" x2=\"22\" y2=\"9\"/><line x1=\"12\" y1=\"12\" x2=\"22\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"14\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"2\" y1=\"6\" x2=\"12\" y2=\"6\"/><line x1=\"2\" y1=\"9\" x2=\"12\" y2=\"9\"/><line x1=\"2\" y1=\"12\" x2=\"12\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatNone: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"3\" y1=\"19\" x2=\"17\" y2=\"19\"/></svg>`,\n originalSize:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/></svg>`,\n deleteImg: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n // Video format operations\n videoAlign: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"23 7 16 12 23 17 23 7\"/><rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\"/></svg>`,\n deleteVideo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n // Format painter operations\n copyFormat: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`,\n pasteFormat: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\"/><path d=\"m9 14 2 2 4-4\"/></svg>`,\n removeFormat:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/></svg>`,\n // Table\n table: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>`,\n // Color\n textColor: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/></svg>`,\n highlightColor: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\"/></svg>`,\n noColor: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\"/><line x1=\"20\" y1=\"4\" x2=\"4\" y2=\"20\"/></svg>`,\n back: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 18 9 12 15 6\"/></svg>`,\n};\n\nconst COLOR_PRESETS = [\n // Grayscale\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n // Saturated\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n // Pastel\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\n];\n\nfunction makeColorSubItems(colorType) {\n const label = colorType === 'foreColor' ? 'Text Color' : 'Highlight Color';\n const localeKey = colorType === 'foreColor' ? 'textColor' : 'highlightColor';\n return () => [\n { back: true, label, localeKey, navigate: () => defaultItems },\n { colorPalette: true, colorType },\n ];\n}\n\nconst defaultItems = [\n { name: 'cut', label: 'Cut', icon: ICONS.cut, action: () => document.execCommand('cut') },\n { name: 'copy', label: 'Copy', icon: ICONS.copy, action: () => document.execCommand('copy') },\n { name: 'paste', label: 'Paste', icon: ICONS.paste, action: (ctx) => {\n if (!navigator.clipboard) return;\n const editable = ctx.layoutInfo && ctx.layoutInfo.editable;\n if (!editable) return;\n // Prefer read() to get rich HTML; fall back to readText() for plain text\n const doInsert = (html, text) => {\n editable.focus();\n if (html) {\n const clean = sanitiseHTML(html);\n document.execCommand('insertHTML', false, clean);\n } else if (text) {\n document.execCommand('insertText', false, text);\n }\n ctx.invoke('editor.afterCommand');\n };\n if (typeof navigator.clipboard.read === 'function') {\n navigator.clipboard.read().then((items) => {\n for (const item of items) {\n if (item.types.includes('text/html')) {\n item.getType('text/html').then((blob) => blob.text()).then((html) => doInsert(html, null));\n return;\n }\n }\n // No HTML item — fall through to plain text\n navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});\n }).catch(() => {\n // read() denied → try readText() as fallback\n navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});\n });\n } else if (typeof navigator.clipboard.readText === 'function') {\n navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});\n }\n } },\n { separator: true },\n { name: 'bold', label: 'Bold', icon: ICONS.bold, action: (ctx) => ctx.invoke('editor.bold') },\n { name: 'italic', label: 'Italic', icon: ICONS.italic, action: (ctx) => ctx.invoke('editor.italic') },\n { name: 'underline', label: 'Underline', icon: ICONS.underline, action: (ctx) => ctx.invoke('editor.underline') },\n { separator: true },\n { name: 'textColor', label: 'Text Color', icon: ICONS.textColor, colorStrip: 'foreColor', navigate: makeColorSubItems('foreColor') },\n { name: 'highlightColor', label: 'Highlight Color', icon: ICONS.highlightColor, colorStrip: 'hiliteColor', navigate: makeColorSubItems('hiliteColor') },\n { separator: true },\n { name: 'copyFormat', label: 'Copy Format', icon: ICONS.copyFormat, action: (ctx) => ctx.invoke('contextMenu.copyFormat') },\n { name: 'pasteFormat', label: 'Paste Format', icon: ICONS.pasteFormat, action: (ctx) => ctx.invoke('contextMenu.pasteFormat'), disabled: (ctx) => !ctx.invoke('contextMenu.hasCopiedFormat') },\n { name: 'removeFormat', label: 'Remove Format', icon: ICONS.removeFormat, action: (ctx) => ctx.invoke('contextMenu.removeFormat') },\n { separator: true },\n { name: 'link', label: 'Insert Link', icon: ICONS.link, action: (ctx) => ctx.invoke('linkDialog.show') },\n { name: 'image', label: 'Insert Image', icon: ICONS.image, action: (ctx) => ctx.invoke('imageDialog.show') },\n { name: 'video', label: 'Insert Video', icon: ICONS.video, action: (ctx) => ctx.invoke('videoDialog.show') },\n { name: 'table', label: 'Insert Table', icon: ICONS.table, tableGrid: true },\n];\n\nexport class ContextMenu {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options || {};\n this._items = (this.options.contextMenu && this.options.contextMenu.items) || defaultItems;\n this.el = null;\n this._disposers = [];\n this._menuDisposers = []; // disposers for dynamically-rendered menu buttons\n this._lastX = 0;\n this._lastY = 0;\n this._copiedFormat = null;\n this._savedRange = null;\n }\n\n initialize() {\n this.el = createElement('div', { class: 'an-contextmenu', role: 'menu', 'aria-hidden': 'true' });\n this.el.style.display = 'none';\n document.body.appendChild(this.el);\n\n this._renderItems(this._items);\n\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (editable) {\n this._disposers.push(on(editable, 'contextmenu', (e) => this._onContextMenu(e)));\n }\n\n this._disposers.push(on(document, 'click', (e) => this._maybeHide(e)));\n this._disposers.push(on(document, 'keydown', (e) => { if (e.key === 'Escape') this.hide(); }));\n this._disposers.push(on(window, 'scroll', () => this.hide(), { passive: true }));\n\n return this;\n }\n\n destroy() {\n this._menuDisposers.forEach((d) => { try { d(); } catch (e) {} });\n this._menuDisposers = [];\n this._disposers.forEach((d) => { try { d(); } catch (e) {} });\n this._disposers = [];\n if (this.el && this.el.parentNode) this.el.parentNode.removeChild(this.el);\n this.el = null;\n }\n\n _renderItems(items) {\n // Clean up previously registered per-item listeners\n this._menuDisposers.forEach((d) => d());\n this._menuDisposers = [];\n\n if (!this.el) return;\n this.el.innerHTML = '';\n\n items.forEach((it) => {\n if (it.separator || it.sep) {\n this.el.appendChild(createElement('div', { class: 'an-context-sep' }));\n return;\n }\n\n // Back-navigation header\n if (it.back) {\n const backBtn = createElement('button', { type: 'button', class: 'an-context-back' });\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = ICONS.back;\n backBtn.appendChild(iconSpan);\n const backLabel = (it.localeKey && this.context.locale.contextMenu[it.localeKey]) || it.label || this.context.locale.contextMenu.back || 'Back';\n backBtn.appendChild(createElement('span', { class: 'an-context-label' }, [backLabel]));\n const off = on(backBtn, 'click', (e) => {\n e.stopPropagation();\n const curLeft = parseFloat(this.el.style.left);\n const curTop = parseFloat(this.el.style.top);\n this._renderItems(it.navigate());\n this._reposition(curLeft, curTop);\n });\n this._menuDisposers.push(off);\n this.el.appendChild(backBtn);\n return;\n }\n\n // Submenu-navigate item (shows ▶ chevron, re-renders without closing)\n if (it.navigate) {\n const btn = createElement('button', { type: 'button', class: 'an-context-item an-context-submenu', 'data-name': it.name || '' });\n if (it.icon) {\n if (it.colorStrip) {\n // Toolbar-style icon: SVG stacked above a colored strip\n const iconWrap = createElement('span', { class: 'an-context-icon an-context-icon--color', 'aria-hidden': 'true' });\n const svgSpan = createElement('span', { class: 'an-context-icon-svg' });\n svgSpan.innerHTML = it.icon;\n const strip = createElement('span', { class: 'an-context-color-strip' });\n strip.style.background = this._getSelectionColor(it.colorStrip);\n iconWrap.appendChild(svgSpan);\n iconWrap.appendChild(strip);\n btn.appendChild(iconWrap);\n } else {\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = it.icon;\n btn.appendChild(iconSpan);\n }\n }\n btn.appendChild(createElement('span', { class: 'an-context-label' }, [(this.context.locale.contextMenu[it.name] || it.label || it.name)]));\n const chevron = createElement('span', { class: 'an-context-chevron', 'aria-hidden': 'true' });\n chevron.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 18 15 12 9 6\"/></svg>`;\n btn.appendChild(chevron);\n const off = on(btn, 'click', (e) => {\n e.stopPropagation();\n const curLeft = parseFloat(this.el.style.left);\n const curTop = parseFloat(this.el.style.top);\n this._renderItems(it.navigate());\n this._reposition(curLeft, curTop);\n });\n this._menuDisposers.push(off);\n this.el.appendChild(btn);\n return;\n }\n\n // Color palette item — renders inline color swatches\n if (it.colorPalette) {\n const palette = createElement('div', { class: 'an-context-color-palette' });\n COLOR_PRESETS.forEach((color) => {\n const sw = createElement('div', {\n class: 'an-context-color-swatch',\n title: color,\n role: 'button',\n 'aria-label': color,\n });\n sw.style.background = color;\n const offSw = on(sw, 'click', (e) => { e.stopPropagation(); this._applyColor(it.colorType, color); });\n this._menuDisposers.push(offSw);\n palette.appendChild(sw);\n });\n if (it.colorType === 'hiliteColor') {\n const noColor = createElement('div', {\n class: 'an-context-color-swatch an-context-color-none',\n title: this.context.locale.contextMenu.noHighlight || 'No highlight',\n role: 'button',\n 'aria-label': this.context.locale.contextMenu.noHighlight || 'No highlight',\n });\n noColor.innerHTML = ICONS.noColor;\n const offNo = on(noColor, 'click', (e) => { e.stopPropagation(); this._applyColor('hiliteColor', 'transparent'); });\n this._menuDisposers.push(offNo);\n palette.appendChild(noColor);\n }\n this.el.appendChild(palette);\n\n // Custom color row\n const customRow = createElement('div', { class: 'an-context-color-custom' });\n const colorInput = createElement('input', {\n type: 'color',\n value: it.colorType === 'foreColor' ? '#000000' : '#ffff00',\n title: this.context.locale.contextMenu.customColor || 'Custom color',\n 'aria-label': this.context.locale.contextMenu.customColor || 'Custom color',\n });\n const customLabel = createElement('span', {}, [this.context.locale.contextMenu.customColorLabel || 'Custom…']);\n const offCustom = on(colorInput, 'change', () => this._applyColor(it.colorType, colorInput.value));\n this._menuDisposers.push(offCustom);\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n this.el.appendChild(customRow);\n return;\n }\n\n // Table grid picker item — expands an inline grid panel when clicked\n if (it.tableGrid) {\n const GRID_ROWS = 8, GRID_COLS = 8;\n const wrapper = createElement('div', { class: 'an-context-table-wrap' });\n\n const headerBtn = createElement('button', { type: 'button', class: 'an-context-item an-context-submenu', 'data-name': it.name || 'table' });\n if (it.icon) {\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = it.icon;\n headerBtn.appendChild(iconSpan);\n }\n headerBtn.appendChild(createElement('span', { class: 'an-context-label' }, [this.context.locale.contextMenu.table || it.label || 'Insert Table']));\n const chevron = createElement('span', { class: 'an-context-chevron', 'aria-hidden': 'true' });\n chevron.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 18 15 12 9 6\"/></svg>`;\n headerBtn.appendChild(chevron);\n\n const panel = createElement('div', { class: 'an-context-table-grid-panel' });\n panel.style.display = 'none';\n\n const gridEl = createElement('div', { class: 'an-table-grid' });\n gridEl.style.gridTemplateColumns = `repeat(${GRID_COLS}, 16px)`;\n const labelEl = createElement('div', { class: 'an-table-label' });\n labelEl.textContent = 'Insert Table';\n\n const cells = [];\n for (let r = 1; r <= GRID_ROWS; r++) {\n for (let c = 1; c <= GRID_COLS; c++) {\n const cell = createElement('div', { class: 'an-table-cell', 'data-row': String(r), 'data-col': String(c) });\n cell.style.width = '16px';\n cell.style.height = '16px';\n cells.push(cell);\n gridEl.appendChild(cell);\n }\n }\n\n const setHighlight = (rows, cols) => {\n cells.forEach((cell) => {\n cell.classList.toggle('active', +cell.dataset.row <= rows && +cell.dataset.col <= cols);\n });\n labelEl.textContent = (rows && cols) ? `${cols} × ${rows}` : (this.context.locale.contextMenu.table || 'Insert Table');\n };\n\n panel.appendChild(gridEl);\n panel.appendChild(labelEl);\n\n let expanded = false;\n const offHeader = on(headerBtn, 'click', (e) => {\n e.stopPropagation();\n expanded = !expanded;\n panel.style.display = expanded ? '' : 'none';\n chevron.style.transform = expanded ? 'rotate(90deg)' : '';\n this._reposition();\n });\n this._menuDisposers.push(offHeader);\n\n const offMove = on(gridEl, 'mousemove', (e) => {\n const cell = e.target.closest('[data-row]');\n if (!cell) return;\n setHighlight(+cell.dataset.row, +cell.dataset.col);\n });\n const offLeave = on(gridEl, 'mouseleave', () => setHighlight(0, 0));\n const offClick = on(gridEl, 'click', (e) => {\n const cell = e.target.closest('[data-row]');\n if (!cell) return;\n const rows = +cell.dataset.row;\n const cols = +cell.dataset.col;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (editable && this._savedRange) {\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n }\n this.hide();\n this.context.invoke('editor.insertTable', cols, rows);\n });\n this._menuDisposers.push(offMove, offLeave, offClick);\n\n wrapper.appendChild(headerBtn);\n wrapper.appendChild(panel);\n this.el.appendChild(wrapper);\n return;\n }\n\n // Regular item\n const btn = createElement('button', { type: 'button', class: 'an-context-item', 'data-name': it.name || '' });\n if (typeof it.disabled === 'function' ? it.disabled(this.context) : !!it.disabled) btn.disabled = true;\n if (it.icon) {\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = it.icon;\n btn.appendChild(iconSpan);\n }\n btn.appendChild(createElement('span', { class: 'an-context-label' }, [(this.context.locale.contextMenu[it.name] || it.label || it.name)]));\n const off = on(btn, 'click', (e) => {\n e.stopPropagation();\n this.hide();\n try { it.action(this.context); } catch (err) { console.error(err); }\n });\n this._menuDisposers.push(off);\n this.el.appendChild(btn);\n });\n }\n\n _onContextMenu(event) {\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable) return;\n if (!editable.contains(event.target)) return;\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n event.preventDefault();\n this._lastX = event.clientX;\n this._lastY = event.clientY;\n const winSel = window.getSelection();\n this._savedRange = (winSel && winSel.rangeCount > 0) ? winSel.getRangeAt(0).cloneRange() : null;\n this._renderItems(this._items);\n this.showAt(event.clientX, event.clientY);\n }\n\n _maybeHide(event) {\n if (!this.el) return;\n if (!this.el.contains(event.target)) this.hide();\n }\n\n showAt(x, y) {\n if (!this.el) return;\n this.el.style.display = 'block';\n this._reposition(x, y);\n this.el.setAttribute('aria-hidden', 'false');\n }\n\n _reposition(x, y) {\n if (!this.el) return;\n const rx = x !== undefined ? x : this._lastX;\n const ry = y !== undefined ? y : this._lastY;\n const rect = this.el.getBoundingClientRect();\n let left = rx;\n let top = ry;\n if (left + rect.width > window.innerWidth) left = window.innerWidth - rect.width - 8;\n if (left < 8) left = 8;\n if (top + rect.height > window.innerHeight) top = window.innerHeight - rect.height - 8;\n if (top < 8) top = 8;\n\n // Avoid covering the saved selection range\n if (this._savedRange) {\n try {\n const sel = this._savedRange.getBoundingClientRect();\n if (sel.width > 0 || sel.height > 0) {\n const overlaps = top < sel.bottom && (top + rect.height) > sel.top &&\n left < sel.right && (left + rect.width) > sel.left;\n if (overlaps) {\n const belowTop = sel.bottom + 6;\n if (belowTop + rect.height <= window.innerHeight - 8) {\n top = belowTop;\n } else {\n top = Math.max(8, sel.top - rect.height - 6);\n }\n }\n }\n } catch (_) { /* stale range — ignore */ }\n }\n\n this.el.style.left = `${left}px`;\n this.el.style.top = `${top}px`;\n }\n\n hide() {\n if (!this.el) return;\n this.el.style.display = 'none';\n this.el.setAttribute('aria-hidden', 'true');\n }\n\n // ---------------------------------------------------------------------------\n // Format operations (Copy Format / Paste Format / Remove Format)\n // ---------------------------------------------------------------------------\n\n /** Read the current selection's text or highlight color for the strip.\n * @param {'foreColor'|'hiliteColor'} type\n * @returns {string} CSS color string\n */\n _getSelectionColor(type) {\n const range = this._savedRange;\n if (!range) return type === 'foreColor' ? '#000000' : 'transparent';\n let node = range.startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node) return type === 'foreColor' ? '#000000' : 'transparent';\n const cs = window.getComputedStyle(node);\n if (type === 'foreColor') {\n return cs.color || '#000000';\n }\n const bg = cs.backgroundColor;\n return (!bg || bg === 'rgba(0, 0, 0, 0)' || bg === 'transparent') ? 'transparent' : bg;\n }\n\n /** Restore selection, apply a color command, then hide the menu. */\n _applyColor(type, color) {\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable || !this._savedRange) return;\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n document.execCommand(type, false, color);\n this.context.invoke('editor.afterCommand');\n this.hide();\n }\n\n /** Returns true if a format has been copied — used to disable Paste Format. */\n hasCopiedFormat() { return !!this._copiedFormat; }\n\n /** Snapshot inline styles at the selection anchor node. */\n copyFormat() {\n const range = this._savedRange;\n if (!range) return;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n let node = range.startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || !editable || !editable.contains(node)) return;\n\n // Walk up to collect explicitly-set inline properties from the nearest styled ancestor\n const cs = window.getComputedStyle(node);\n\n // Detect if an explicit font-family / font-size is set on an element (not just inherited)\n const explicitFontFamily = this._findExplicitStyle(node, editable, 'fontFamily');\n const explicitFontSize = this._findExplicitStyle(node, editable, 'fontSize');\n\n this._copiedFormat = {\n bold: parseInt(cs.fontWeight, 10) >= 700,\n italic: cs.fontStyle === 'italic' || cs.fontStyle === 'oblique',\n underline: (cs.textDecorationLine || '').includes('underline'),\n strikethrough: (cs.textDecorationLine || '').includes('line-through'),\n fontFamily: explicitFontFamily,\n fontSize: explicitFontSize,\n color: this._isDefaultColor(cs.color) ? null : cs.color,\n backgroundColor: cs.backgroundColor,\n };\n }\n\n /** Walk up the tree looking for a property explicitly set in inline style. Returns null if only inherited. */\n _findExplicitStyle(node, boundary, prop) {\n let el = node;\n while (el && el !== boundary && el !== document.body) {\n if (el.style && el.style[prop]) return el.style[prop];\n // also check font element attributes\n if (el.nodeName === 'FONT') {\n if (prop === 'fontFamily' && el.getAttribute('face')) return el.getAttribute('face');\n if (prop === 'fontSize' && el.getAttribute('size')) {\n // font size attribute is 1-7; skip these since we need px\n return null;\n }\n }\n el = el.parentElement;\n }\n return null;\n }\n\n /** Checks if a computed color looks like the default browser text color (black). */\n _isDefaultColor(color) {\n return !color || color === 'rgb(0, 0, 0)' || color === 'rgba(0, 0, 0, 0)' || color === 'transparent';\n }\n\n /** Apply the most-recently copied format to the saved selection. */\n pasteFormat() {\n if (!this._copiedFormat || !this._savedRange) return;\n const fmt = this._copiedFormat;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable) return;\n\n // CRITICAL: focus the editable FIRST, then restore selection.\n // Calling focus() after addRange() can wipe the selection in Chrome/Firefox.\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n\n // Strip existing inline formatting so we start from a clean state.\n // After removeFormat, bold/italic/underline/strikethrough are guaranteed off.\n document.execCommand('removeFormat');\n\n // Apply each format positively — no toggle-check needed after removeFormat.\n if (fmt.bold) document.execCommand('bold');\n if (fmt.italic) document.execCommand('italic');\n if (fmt.underline) document.execCommand('underline');\n if (fmt.strikethrough) document.execCommand('strikeThrough');\n\n if (fmt.color) document.execCommand('foreColor', false, fmt.color);\n\n const isTransparent = (c) => !c || c === 'rgba(0, 0, 0, 0)' || c === 'transparent';\n if (!isTransparent(fmt.backgroundColor)) {\n document.execCommand('hiliteColor', false, fmt.backgroundColor);\n }\n\n // Font family — apply BEFORE font-size DOM manipulation so the selection is still intact.\n if (fmt.fontFamily) {\n document.execCommand('fontName', false, fmt.fontFamily);\n }\n\n // Font size — use a unique data-marker to avoid touching pre-existing font[size=\"7\"] nodes.\n if (fmt.fontSize) {\n const marker = `fs-${Date.now()}`;\n // Snapshot pre-existing font[size=\"7\"] BEFORE execCommand so we don't accidentally\n // replace nodes that were already in the document (the comment below was aspirational\n // but the original code never actually excluded them — this Set approach is the fix).\n const preExisting = new Set(editable.querySelectorAll('font[size=\"7\"]'));\n document.execCommand('fontSize', false, '7');\n // Mark only the NEWLY created font[size=\"7\"] elements.\n editable.querySelectorAll('font[size=\"7\"]').forEach((el) => {\n if (!preExisting.has(el)) el.setAttribute('data-an-tmp', marker);\n });\n editable.querySelectorAll(`[data-an-tmp=\"${marker}\"]`).forEach((el) => {\n const span = document.createElement('span');\n span.style.fontSize = fmt.fontSize;\n el.parentNode.insertBefore(span, el);\n while (el.firstChild) span.appendChild(el.firstChild);\n el.parentNode.removeChild(el);\n });\n }\n\n this.context.invoke('editor.afterCommand');\n }\n\n /** Strip all inline formatting from the saved selection. */\n removeFormat() {\n if (!this._savedRange) return;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable) return;\n\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n\n document.execCommand('removeFormat');\n\n const range = sel.getRangeAt(0);\n const root = range.commonAncestorContainer;\n const rootEl = root.nodeType === Node.TEXT_NODE ? root.parentElement : root;\n const iter = document.createNodeIterator(rootEl, NodeFilter.SHOW_ELEMENT);\n let el;\n while ((el = iter.nextNode())) {\n if (!editable.contains(el) || el === editable) continue;\n try { if (range.intersectsNode(el)) el.removeAttribute('style'); } catch { /* ignore */ }\n }\n\n this.context.invoke('editor.afterCommand');\n }\n}\n\nexport default ContextMenu;\n","/**\n * ShortcutsDialog.js - Modal dialog listing all keyboard shortcuts.\n * Opened via the toolbar '?' button or Shift+? inside the editor.\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\n\nconst SHORTCUTS = [\n {\n category: 'Text Formatting',\n items: [\n { keys: 'Ctrl + B', action: 'Bold' },\n { keys: 'Ctrl + I', action: 'Italic' },\n { keys: 'Ctrl + U', action: 'Underline' },\n { keys: 'Ctrl + K', action: 'Insert / edit link' },\n ],\n },\n {\n category: 'History',\n items: [\n { keys: 'Ctrl + Z', action: 'Undo' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Redo' },\n ],\n },\n {\n category: 'Selection & Navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Select all content' },\n { keys: 'Tab', action: 'Indent list item / insert spaces' },\n { keys: 'Shift + Tab', action: 'Outdent list item' },\n ],\n },\n {\n category: 'Clipboard',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Paste as plain text' },\n ],\n },\n {\n category: 'Find & Replace',\n items: [\n { keys: 'Ctrl + F', action: 'Find in document' },\n { keys: 'Ctrl + H', action: 'Find & Replace' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Show this keyboard shortcuts dialog' },\n ],\n },\n];\n\nexport class ShortcutsDialog {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._dialog = null;\n this._closeBtn = null;\n this._disposers = [];\n }\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n show() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._closeBtn && this._closeBtn.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n }\n\n _buildDialog() {\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': this.context.locale.shortcutsDialog.ariaLabel,\n });\n\n const box = createElement('div', { class: 'an-dialog-box an-shortcuts-box' });\n\n // Title row with close button\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = this.context.locale.shortcutsDialog.title;\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n 'aria-label': this.context.locale.shortcutsDialog.close,\n });\n closeBtn.textContent = '×';\n this._closeBtn = closeBtn;\n titleRow.append(title, closeBtn);\n box.appendChild(titleRow);\n\n const shortcuts = this.context.locale.shortcutsDialog.shortcuts || SHORTCUTS;\n shortcuts.forEach(({ category, items }) => {\n const catEl = createElement('div', { class: 'an-shortcuts-cat' });\n catEl.textContent = category;\n box.appendChild(catEl);\n\n const table = createElement('div', { class: 'an-shortcuts-table' });\n items.forEach(({ keys, action }) => {\n const row = createElement('div', { class: 'an-shortcuts-row' });\n const keyEl = createElement('span', { class: 'an-shortcuts-key' });\n keyEl.textContent = keys;\n const actEl = createElement('span', { class: 'an-shortcuts-action' });\n actEl.textContent = action;\n row.append(keyEl, actEl);\n table.appendChild(row);\n });\n box.appendChild(table);\n });\n\n overlay.appendChild(box);\n\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n this._disposers.push(d1, d2);\n\n return overlay;\n }\n}\n","/**\n * FindReplace.js - Find & Replace dialog\n *\n * Opens via Ctrl+F (find only) or Ctrl+H (find + replace).\n * Uses TreeWalker to locate text matches and wraps them with <mark> elements\n * for highlighting. Supports case-sensitive search, Prev/Next navigation and\n * single / replace-all replacement.\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\n\nexport class FindReplace {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n\n /** @type {HTMLElement|null} */\n this._dialog = null;\n /** @type {HTMLInputElement|null} */\n this._findInput = null;\n /** @type {HTMLInputElement|null} */\n this._replaceInput = null;\n /** @type {HTMLInputElement|null} */\n this._caseCheckbox = null;\n /** @type {HTMLElement|null} */\n this._counterEl = null;\n /** @type {HTMLElement|null} */\n this._closeBtn = null;\n\n /** Live matches — each entry is { mark: HTMLElement } after highlighting */\n this._matches = [];\n this._currentIndex = -1;\n this._caseSensitive = false;\n /** @type {'find'|'replace'} */\n this._mode = 'find';\n\n /** Cached compiled regex — reused when query and case-sensitivity are unchanged */\n this._queryRegex = null;\n this._lastQuery = null;\n this._lastCaseSensitive = null;\n\n this._disposers = [];\n this._removeTrap = null;\n this._focusTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n clearTimeout(this._focusTimer);\n this._focusTimer = null;\n this._clearHighlights();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the dialog in 'find' or 'replace' mode.\n * @param {'find'|'replace'} [mode='find']\n */\n show(mode = 'find') {\n this._mode = mode;\n this._updateMode();\n this._open();\n // Pre-select whatever was previously typed so the user can retype immediately\n clearTimeout(this._focusTimer);\n this._focusTimer = setTimeout(() => {\n if (this._findInput) {\n this._findInput.select();\n this._findInput.focus();\n }\n }, 50);\n }\n\n // ---------------------------------------------------------------------------\n // Open / close\n // ---------------------------------------------------------------------------\n\n _open() {\n if (!this._dialog) return;\n // If already visible, just focus the search input — don't re-trap.\n if (this._dialog.style.display === 'flex') {\n if (this._findInput) this._findInput.focus();\n return;\n }\n this._dialog.style.display = 'flex';\n // Release any previous trap before installing a new one.\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n }\n\n _close() {\n this._clearHighlights();\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n // Return focus to the editor\n this.context.invoke('editor.focus');\n }\n\n _updateMode() {\n if (!this._dialog) return;\n const replaceRow = this._dialog.querySelector('.an-fr-replace-row');\n const replaceActions = this._dialog.querySelector('.an-fr-replace-actions');\n const title = this._dialog.querySelector('.an-dialog-title');\n\n const isReplace = this._mode === 'replace';\n if (replaceRow) replaceRow.style.display = isReplace ? '' : 'none';\n if (replaceActions) replaceActions.style.display = isReplace ? '' : 'none';\n if (title) title.textContent = isReplace ? this.context.locale.findReplace.findReplaceTitle : this.context.locale.findReplace.findTitle;\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.findReplace;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay an-fr-dialog',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.findReplaceTitle,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n // ---- Title row ----\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.findTitle;\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n 'aria-label': 'Close',\n });\n closeBtn.textContent = L.close;\n this._closeBtn = closeBtn;\n titleRow.append(title, closeBtn);\n box.appendChild(titleRow);\n\n // ---- Find row ----\n const findRow = createElement('div', { class: 'an-fr-find-row' });\n const findInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.findPlaceholder,\n 'aria-label': L.searchAriaLabel,\n });\n this._findInput = findInput;\n findRow.appendChild(findInput);\n box.appendChild(findRow);\n\n // ---- Options row (case-sensitive toggle + match counter) ----\n const optRow = createElement('div', { class: 'an-fr-options-row' });\n const caseLabel = createElement('label', { class: 'an-label an-label-inline' });\n const caseCheckbox = createElement('input', {\n type: 'checkbox',\n 'aria-label': 'Case sensitive',\n });\n this._caseCheckbox = caseCheckbox;\n caseLabel.append(caseCheckbox, document.createTextNode(L.caseSensitive));\n const counter = createElement('span', { class: 'an-fr-counter' });\n this._counterEl = counter;\n optRow.append(caseLabel, counter);\n box.appendChild(optRow);\n\n // ---- Find actions ----\n const findActions = createElement('div', { class: 'an-dialog-actions an-fr-find-actions' });\n const prevBtn = createElement('button', { type: 'button', class: 'an-btn' });\n prevBtn.textContent = L.prevBtn;\n const nextBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n nextBtn.textContent = L.nextBtn;\n findActions.append(prevBtn, nextBtn);\n box.appendChild(findActions);\n\n // ---- Replace row (hidden by default) ----\n const replaceRow = createElement('div', { class: 'an-fr-replace-row' });\n replaceRow.style.display = 'none';\n const replaceInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.replacePlaceholder,\n 'aria-label': L.replaceAriaLabel,\n });\n this._replaceInput = replaceInput;\n replaceRow.appendChild(replaceInput);\n box.appendChild(replaceRow);\n\n // ---- Replace actions (hidden by default) ----\n const replaceActions = createElement('div', { class: 'an-dialog-actions an-fr-replace-actions' });\n replaceActions.style.display = 'none';\n const replaceBtn = createElement('button', { type: 'button', class: 'an-btn' });\n replaceBtn.textContent = L.replaceBtn;\n const replaceAllBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n replaceAllBtn.textContent = L.replaceAllBtn;\n replaceActions.append(replaceBtn, replaceAllBtn);\n box.appendChild(replaceActions);\n\n overlay.appendChild(box);\n\n // ---- Event bindings ----\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d3 = on(findInput, 'input', () => this._onSearch());\n const d4 = on(caseCheckbox, 'change', () => {\n this._caseSensitive = caseCheckbox.checked;\n this._onSearch();\n });\n const d5 = on(nextBtn, 'click', () => this._next());\n const d6 = on(prevBtn, 'click', () => this._prev());\n const d7 = on(replaceBtn, 'click', () => this._replace());\n const d8 = on(replaceAllBtn, 'click', () => this._replaceAll());\n const d9 = on(findInput, 'keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.shiftKey ? this._prev() : this._next();\n }\n });\n const d10 = on(replaceInput, 'keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._replace();\n }\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Search logic\n // ---------------------------------------------------------------------------\n\n _onSearch() {\n this._clearHighlights();\n const query = this._findInput ? this._findInput.value : '';\n if (!query) {\n this._updateCounter();\n return;\n }\n this._findAndHighlight(query);\n this._updateCounter();\n }\n\n /**\n * Finds all occurrences of `query` in the editable area text nodes,\n * then wraps each match in a <mark class=\"an-highlight\"> element.\n * Iterates text nodes in reverse so earlier offsets remain valid.\n * @param {string} query\n */\n _findAndHighlight(query) {\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n\n // Collect raw matches: { node, start, end }\n const rawMatches = this._findRawMatches(query, editable);\n if (rawMatches.length === 0) return;\n\n this._currentIndex = 0;\n\n // Wrap matches in reverse order so earlier text offsets stay valid when\n // later sections of the same text node are split by surroundContents().\n // Use push() instead of unshift() to avoid O(n²) shifting on every insert;\n // reverse() at the end restores forward document order in O(n).\n for (let i = rawMatches.length - 1; i >= 0; i--) {\n const { node, start, end } = rawMatches[i];\n try {\n const range = document.createRange();\n range.setStart(node, start);\n range.setEnd(node, end);\n const mark = document.createElement('mark');\n mark.className = 'an-highlight';\n range.surroundContents(mark);\n this._matches.push({ mark });\n } catch (_) {\n // surroundContents fails when the range crosses element boundaries.\n // This can happen with <br> inside matched text — skip safely.\n this._matches.push({ mark: null });\n }\n }\n this._matches.reverse(); // O(n) — restore forward document order\n\n // Drop entries where wrapping failed so the counter and navigation are accurate\n this._matches = this._matches.filter((m) => m.mark);\n if (this._matches.length === 0) return;\n\n // Highlight the first (current) match\n if (this._matches[0] && this._matches[0].mark) {\n this._matches[0].mark.className = 'an-highlight an-highlight-current';\n this._matches[0].mark.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n }\n\n /**\n * Walks all text nodes under `root` and returns positional match descriptors.\n * @param {string} query\n * @param {HTMLElement} root\n * @returns {{ node: Text, start: number, end: number }[]}\n */\n _findRawMatches(query, root) {\n const results = [];\n // Reuse compiled regex when query and case-sensitivity haven't changed\n if (this._lastQuery !== query || this._lastCaseSensitive !== this._caseSensitive) {\n const flags = this._caseSensitive ? 'g' : 'gi';\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n this._queryRegex = new RegExp(escaped, flags);\n this._lastQuery = query;\n this._lastCaseSensitive = this._caseSensitive;\n }\n const re = this._queryRegex;\n\n const walker = document.createTreeWalker(root, 0x4 /* NodeFilter.SHOW_TEXT */);\n let node;\n while ((node = walker.nextNode())) {\n re.lastIndex = 0;\n let m;\n while ((m = re.exec(node.textContent)) !== null) {\n results.push({ node, start: m.index, end: m.index + m[0].length });\n }\n }\n return results;\n }\n\n // ---------------------------------------------------------------------------\n // Navigation\n // ---------------------------------------------------------------------------\n\n _next() {\n if (this._matches.length === 0) return;\n this._currentIndex = (this._currentIndex + 1) % this._matches.length;\n this._scrollToMatch(this._currentIndex);\n this._updateCounter();\n }\n\n _prev() {\n if (this._matches.length === 0) return;\n this._currentIndex = (this._currentIndex - 1 + this._matches.length) % this._matches.length;\n this._scrollToMatch(this._currentIndex);\n this._updateCounter();\n }\n\n _scrollToMatch(index) {\n const match = this._matches[index];\n if (!match || !match.mark) return;\n // Update CSS classes\n this._matches.forEach((m, i) => {\n if (m.mark) {\n m.mark.className = i === index\n ? 'an-highlight an-highlight-current'\n : 'an-highlight';\n }\n });\n match.mark.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n\n // ---------------------------------------------------------------------------\n // Replace\n // ---------------------------------------------------------------------------\n\n _replace() {\n if (this._matches.length === 0 || this._currentIndex < 0) return;\n const match = this._matches[this._currentIndex];\n if (!match || !match.mark || !match.mark.parentNode) return;\n\n const replacement = this._replaceInput ? this._replaceInput.value : '';\n const parent = match.mark.parentNode;\n const textNode = document.createTextNode(replacement);\n parent.insertBefore(textNode, match.mark);\n parent.removeChild(match.mark);\n parent.normalize();\n this.context.invoke('editor.afterCommand');\n const savedIndex = this._currentIndex;\n this._onSearch();\n if (this._matches.length > 0) {\n this._currentIndex = Math.min(savedIndex, this._matches.length - 1);\n this._scrollToMatch(this._currentIndex);\n this._updateCounter();\n }\n }\n\n _replaceAll() {\n if (this._matches.length === 0) return;\n const replacement = this._replaceInput ? this._replaceInput.value : '';\n\n this._matches.forEach(({ mark }) => {\n if (!mark || !mark.parentNode) return;\n const textNode = document.createTextNode(replacement);\n mark.parentNode.insertBefore(textNode, mark);\n mark.parentNode.removeChild(mark);\n });\n\n if (this.context.layoutInfo.editable) {\n this.context.layoutInfo.editable.normalize();\n }\n this._matches = [];\n this._currentIndex = -1;\n this.context.invoke('editor.afterCommand');\n this._onSearch();\n }\n\n // ---------------------------------------------------------------------------\n // Highlight management\n // ---------------------------------------------------------------------------\n\n /**\n * Removes all <mark class=\"an-highlight\"> elements from the editable area,\n * restoring the original text nodes via normalization.\n */\n _clearHighlights() {\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n\n editable.querySelectorAll('mark.an-highlight').forEach((mark) => {\n const parent = mark.parentNode;\n if (!parent) return;\n while (mark.firstChild) parent.insertBefore(mark.firstChild, mark);\n parent.removeChild(mark);\n });\n // Merge adjacent text nodes after unwrapping\n editable.normalize();\n\n this._matches = [];\n this._currentIndex = -1;\n }\n\n // ---------------------------------------------------------------------------\n // Counter display\n // ---------------------------------------------------------------------------\n\n _updateCounter() {\n if (!this._counterEl) return;\n const total = this._matches.length;\n if (total === 0) {\n const query = this._findInput ? this._findInput.value : '';\n this._counterEl.textContent = query ? 'No results' : '';\n } else {\n this._counterEl.textContent = `${this._currentIndex + 1} / ${total}`;\n }\n }\n}\n","// ImageCropOverlay.js - Inline crop overlay for images inside the editor\n//\n// Architecture:\n// - A dark scrim fills the entire viewport (fixed, z=10100) with a transparent\n// cutout showing the current crop region (clip-path technique).\n// - A \"crop box\" div overlaps the cutout; four corner + four edge handles let\n// the user drag to resize it.\n// - On Confirm: draws the crop region onto an off-screen canvas and replaces\n// img.src with a data-URL. Cross-origin images are caught and a warning is\n// shown instead of crashing.\n// - All pointer listeners are document-level and are torn down after each\n// interaction to avoid leaks.\n\nimport { on } from '../core/dom.js';\n\n// Minimum crop box dimension in CSS pixels\nconst MIN_SIZE = 20;\n\n// Accent colour for handles (synced with $an-primary)\nconst ACCENT = '#3b82f6';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Clamp `value` between `lo` and `hi`. */\nconst clamp = (value, lo, hi) => Math.min(Math.max(value, lo), hi);\n\n/**\n * Attempt to draw `img` onto a canvas even if it was loaded without CORS.\n * Returns a canvas element on success, or null if the image is cross-origin\n * tainted and cannot be read.\n *\n * Strategy:\n * 1. Try directly — works for same-origin and data/blob URLs.\n * 2. Re-load with crossOrigin=\"anonymous\" and retry (needs server ACAO header).\n *\n * @param {HTMLImageElement} img\n * @param {DOMRect} naturalRect - crop region in *natural* image pixels\n * @param {number} renderW - desired output width\n * @param {number} renderH - desired output height\n * @returns {Promise<HTMLCanvasElement|null>}\n */\nfunction drawCropToCanvas(img, naturalRect, renderW, renderH) {\n return new Promise((resolve) => {\n const tryDraw = (source) => {\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(renderW);\n canvas.height = Math.round(renderH);\n const ctx = canvas.getContext('2d');\n try {\n ctx.drawImage(\n source,\n naturalRect.x, naturalRect.y, naturalRect.width, naturalRect.height,\n 0, 0, canvas.width, canvas.height,\n );\n // Access a pixel — this throws if canvas is tainted\n ctx.getImageData(0, 0, 1, 1);\n resolve(canvas);\n } catch (_) {\n resolve(null);\n }\n };\n\n // Fast path — data: / blob: / same-origin\n if (\n img.src.startsWith('data:') ||\n img.src.startsWith('blob:') ||\n img.src.startsWith(window.location.origin)\n ) {\n tryDraw(img);\n return;\n }\n\n // Cross-origin: try a fresh image with crossOrigin=\"anonymous\"\n const tmp = new Image();\n tmp.crossOrigin = 'anonymous';\n tmp.onload = () => tryDraw(tmp);\n tmp.onerror = () => resolve(null);\n // Append cache-buster to avoid serving a cached non-CORS response\n tmp.src = img.src + (img.src.includes('?') ? '&' : '?') + '_an=' + Date.now();\n });\n}\n\n// ---------------------------------------------------------------------------\n// ImageCropOverlay\n// ---------------------------------------------------------------------------\n\nexport class ImageCropOverlay {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLImageElement|null} */\n this._img = null;\n /** Crop box position in viewport px: { x, y, w, h } */\n this._box = null;\n /** Natural-size bounding rect of the image in viewport px */\n this._imgRect = null;\n\n this._scrim = null;\n this._cropBox = null;\n this._handles = {};\n this._toolbar = null;\n this._infoEl = null;\n\n this._dragDisposers = null;\n this._disposers = [];\n }\n\n initialize() {\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n this._close(false);\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Open the crop overlay for the given image.\n * @param {HTMLImageElement} img\n */\n open(img) {\n if (this._scrim) this._close(false); // guard: only one at a time\n\n this._img = img;\n const rect = img.getBoundingClientRect();\n this._imgRect = rect;\n\n // Default crop box = full image, inset 12 px on each side (feels visual)\n const inset = Math.min(12, rect.width * 0.1, rect.height * 0.1);\n this._box = {\n x: rect.left + inset,\n y: rect.top + inset,\n w: rect.width - inset * 2,\n h: rect.height - inset * 2,\n };\n\n this._buildDOM();\n this._updateDOM();\n this._bindEsc();\n }\n\n // ---------------------------------------------------------------------------\n // DOM construction\n // ---------------------------------------------------------------------------\n\n _buildDOM() {\n /* ---- scrim ---- */\n const scrim = document.createElement('div');\n scrim.className = 'an-crop-scrim';\n // Prevent scroll during crop\n scrim.style.cssText = `\n position:fixed; inset:0; z-index:10100;\n cursor:crosshair;\n background: rgba(0,0,0,0.55);\n `;\n // Click on scrim (outside crop box) → cancel\n this._disposers.push(\n on(scrim, 'mousedown', (e) => {\n if (e.target === scrim) this._close(false);\n }),\n );\n\n /* ---- crop box ---- */\n const cropBox = document.createElement('div');\n cropBox.className = 'an-crop-box';\n cropBox.style.cssText = `\n position:fixed; z-index:10101;\n box-sizing:border-box;\n border:2px solid ${ACCENT};\n cursor:move;\n outline: none;\n `;\n\n /* ---- rule-of-thirds grid lines ---- */\n const grid = document.createElement('div');\n grid.className = 'an-crop-grid';\n grid.style.cssText = `\n position:absolute; inset:0; pointer-events:none;\n opacity:0.35;\n `;\n // 2 vertical + 2 horizontal lines\n ['33.33%','66.66%'].forEach((pos) => {\n const vl = document.createElement('div');\n vl.style.cssText = `position:absolute;top:0;bottom:0;left:${pos};width:1px;background:#fff;`;\n const hl = document.createElement('div');\n hl.style.cssText = `position:absolute;left:0;right:0;top:${pos};height:1px;background:#fff;`;\n grid.appendChild(vl);\n grid.appendChild(hl);\n });\n cropBox.appendChild(grid);\n\n /* ---- resize handles ---- */\n const HANDLE_DEFS = [\n { id: 'nw', cur: 'nw-resize', top: '-5px', left: '-5px' },\n { id: 'n', cur: 'n-resize', top: '-5px', left: 'calc(50% - 5px)' },\n { id: 'ne', cur: 'ne-resize', top: '-5px', right: '-5px' },\n { id: 'e', cur: 'e-resize', top: 'calc(50% - 5px)', right: '-5px' },\n { id: 'se', cur: 'se-resize', bottom: '-5px', right: '-5px' },\n { id: 's', cur: 's-resize', bottom: '-5px', left: 'calc(50% - 5px)' },\n { id: 'sw', cur: 'sw-resize', bottom: '-5px', left: '-5px' },\n { id: 'w', cur: 'w-resize', top: 'calc(50% - 5px)', left: '-5px' },\n ];\n\n HANDLE_DEFS.forEach(({ id, cur, ...pos }) => {\n const h = document.createElement('div');\n h.className = `an-crop-handle an-crop-handle-${id}`;\n h.style.cssText = [\n 'position:absolute',\n 'width:10px', 'height:10px',\n `background:${ACCENT}`,\n 'border:2px solid #fff',\n 'border-radius:2px',\n 'box-sizing:border-box',\n `cursor:${cur}`,\n ...Object.entries(pos).map(([k, v]) => `${k}:${v}`),\n ].join(';');\n this._disposers.push(\n on(h, 'mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startHandleDrag(e, id);\n }),\n );\n this._handles[id] = h;\n cropBox.appendChild(h);\n });\n\n /* ---- crop move drag ---- */\n this._disposers.push(\n on(cropBox, 'mousedown', (e) => {\n // Only directly on the box surface (not on a handle)\n if (e.target !== cropBox && e.target !== grid && !(e.target.tagName === 'DIV' && !e.target.className.includes('handle'))) {\n // Let handle mousedown handle it\n return;\n }\n if (e.target.className && e.target.className.includes('an-crop-handle')) return;\n e.preventDefault();\n e.stopPropagation();\n this._startBoxMove(e);\n }),\n );\n\n /* ---- info label ---- */\n const infoEl = document.createElement('div');\n infoEl.className = 'an-crop-info';\n infoEl.style.cssText = `\n position:absolute; bottom:-28px; left:0;\n font:bold 11px/20px system-ui,sans-serif;\n color:#fff; white-space:nowrap;\n pointer-events:none;\n text-shadow: 0 1px 3px rgba(0,0,0,.6);\n `;\n cropBox.appendChild(infoEl);\n this._infoEl = infoEl;\n\n /* ---- floating toolbar ---- */\n const toolbar = document.createElement('div');\n toolbar.className = 'an-crop-toolbar';\n toolbar.style.cssText = `\n position:fixed; z-index:10102;\n background:#1e1e2e; border-radius:6px;\n padding:5px 8px; display:flex; gap:6px;\n align-items:center;\n box-shadow:0 4px 16px rgba(0,0,0,.4);\n font:13px system-ui,sans-serif;\n `;\n\n const confirmBtn = this._makeToolbarBtn('✓ Crop', '#22c55e', () => this._confirm());\n const cancelBtn = this._makeToolbarBtn('✕ Cancel', '#94a3b8', () => this._close(false));\n\n // Aspect ratio lock checkbox\n const arLabel = document.createElement('label');\n arLabel.style.cssText = 'color:#94a3b8;font-size:11px;cursor:pointer;display:flex;align-items:center;gap:4px;';\n const arCheck = document.createElement('input');\n arCheck.type = 'checkbox';\n arCheck.style.accentColor = ACCENT;\n arLabel.appendChild(arCheck);\n arLabel.appendChild(document.createTextNode('Lock ratio'));\n this._arCheck = arCheck;\n\n toolbar.appendChild(confirmBtn);\n toolbar.appendChild(cancelBtn);\n toolbar.appendChild(arLabel);\n this._toolbar = toolbar;\n\n // Prevent toolbar clicks from closing the overlay\n this._disposers.push(\n on(toolbar, 'mousedown', (e) => e.stopPropagation()),\n );\n\n document.body.appendChild(scrim);\n document.body.appendChild(cropBox);\n document.body.appendChild(toolbar);\n\n this._scrim = scrim;\n this._cropBox = cropBox;\n }\n\n _makeToolbarBtn(text, color, handler) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.textContent = text;\n btn.style.cssText = `\n background:none; border:1px solid ${color}; border-radius:4px;\n color:${color}; padding:3px 10px; cursor:pointer; font-size:12px;\n font-family:inherit;\n transition:background 0.12s;\n `;\n btn.addEventListener('mouseover', () => { btn.style.background = color + '22'; });\n btn.addEventListener('mouseout', () => { btn.style.background = 'none'; });\n this._disposers.push(on(btn, 'click', (e) => { e.stopPropagation(); handler(); }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // DOM sync\n // ---------------------------------------------------------------------------\n\n _updateDOM() {\n const { x, y, w, h } = this._box;\n\n this._cropBox.style.left = `${x}px`;\n this._cropBox.style.top = `${y}px`;\n this._cropBox.style.width = `${w}px`;\n this._cropBox.style.height = `${h}px`;\n\n // Scrim cutout via clip-path polygon (punches a transparent hole)\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n // Outer rect → inner rectangle (counterclockwise) = hole\n this._scrim.style.clipPath = [\n `polygon(`,\n `0 0, ${vw}px 0, ${vw}px ${vh}px, 0 ${vh}px, 0 0,`,\n `${x}px ${y}px, ${x}px ${y + h}px, ${x + w}px ${y + h}px, ${x + w}px ${y}px, ${x}px ${y}px`,\n `)`,\n ].join('');\n\n // Info label: natural pixels\n if (this._img) {\n const nw = this._img.naturalWidth || 0;\n const nh = this._img.naturalHeight || 0;\n const dispW = this._imgRect.width || 1;\n const dispH = this._imgRect.height || 1;\n const scale = { x: nw / dispW, y: nh / dispH };\n const cx = clamp(x - this._imgRect.left, 0, dispW);\n const cy = clamp(y - this._imgRect.top, 0, dispH);\n const cw = clamp(w, 0, dispW - cx);\n const ch = clamp(h, 0, dispH - cy);\n this._infoEl.textContent = `${Math.round(cw * scale.x)} × ${Math.round(ch * scale.y)} px`;\n }\n\n // Position toolbar below crop box (or above if near bottom)\n const margin = 8;\n let tbTop = y + h + margin;\n if (tbTop + 40 > window.innerHeight - margin) tbTop = y - 40 - margin;\n this._toolbar.style.left = `${x}px`;\n this._toolbar.style.top = `${tbTop}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Drag: move box\n // ---------------------------------------------------------------------------\n\n _startBoxMove(e) {\n const startX = e.clientX - this._box.x;\n const startY = e.clientY - this._box.y;\n const r = this._imgRect;\n\n const onMove = (me) => {\n this._box.x = clamp(me.clientX - startX, r.left, r.right - this._box.w);\n this._box.y = clamp(me.clientY - startY, r.top, r.bottom - this._box.h);\n this._updateDOM();\n };\n\n this._attachDocDrag(onMove);\n }\n\n // ---------------------------------------------------------------------------\n // Drag: resize handle\n // ---------------------------------------------------------------------------\n\n _startHandleDrag(e, id) {\n const startX = e.clientX;\n const startY = e.clientY;\n const orig = { ...this._box };\n const r = this._imgRect;\n const lockAR = this._arCheck && this._arCheck.checked;\n const aspect = orig.w / (orig.h || 1);\n\n const onMove = (me) => {\n const dx = me.clientX - startX;\n const dy = me.clientY - startY;\n let { x, y, w, h } = orig;\n\n // Apply deltas per handle position\n if (id.includes('e')) w = Math.max(MIN_SIZE, orig.w + dx);\n if (id.includes('s')) h = Math.max(MIN_SIZE, orig.h + dy);\n if (id.includes('w')) { x = Math.min(orig.x + orig.w - MIN_SIZE, orig.x + dx); w = orig.x + orig.w - x; }\n if (id.includes('n')) { y = Math.min(orig.y + orig.h - MIN_SIZE, orig.y + dy); h = orig.y + orig.h - y; }\n\n // Aspect-ratio lock (corner handles)\n if (lockAR && id.length === 2) {\n if (Math.abs(dx) >= Math.abs(dy)) {\n h = w / aspect;\n if (id.includes('n')) y = orig.y + orig.h - h;\n } else {\n w = h * aspect;\n if (id.includes('w')) x = orig.x + orig.w - w;\n }\n }\n\n // Clamp to image bounds\n x = clamp(x, r.left, r.right - MIN_SIZE);\n y = clamp(y, r.top, r.bottom - MIN_SIZE);\n w = clamp(w, MIN_SIZE, r.right - x);\n h = clamp(h, MIN_SIZE, r.bottom - y);\n\n this._box = { x, y, w, h };\n this._updateDOM();\n };\n\n this._attachDocDrag(onMove);\n }\n\n /**\n * Attach mousemove + mouseup to document for the duration of a drag.\n * @param {(e: MouseEvent) => void} onMove\n */\n _attachDocDrag(onMove) {\n const cleanup = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', cleanup);\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n };\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', cleanup, { once: true });\n }\n\n // ---------------------------------------------------------------------------\n // Keyboard\n // ---------------------------------------------------------------------------\n\n _bindEsc() {\n const handler = (e) => {\n if (e.key === 'Escape') { e.preventDefault(); this._close(false); }\n if (e.key === 'Enter') { e.preventDefault(); this._confirm(); }\n };\n document.addEventListener('keydown', handler);\n this._disposers.push(() => document.removeEventListener('keydown', handler));\n }\n\n // ---------------------------------------------------------------------------\n // Confirm / Close\n // ---------------------------------------------------------------------------\n\n async _confirm() {\n const img = this._img;\n if (!img) { this._close(false); return; }\n\n const r = this._imgRect;\n const { x, y, w, h } = this._box;\n\n // Convert display-px crop region → natural-px\n const scaleX = (img.naturalWidth || img.width || 1) / (r.width || 1);\n const scaleY = (img.naturalHeight || img.height || 1) / (r.height || 1);\n\n const natX = Math.round(clamp(x - r.left, 0, r.width) * scaleX);\n const natY = Math.round(clamp(y - r.top, 0, r.height) * scaleY);\n const natW = Math.round(clamp(w, 0, r.width - (x - r.left)) * scaleX);\n const natH = Math.round(clamp(h, 0, r.height - (y - r.top)) * scaleY);\n\n if (natW <= 0 || natH <= 0) { this._close(false); return; }\n\n // Output dimensions = display-pixel crop size (preserve visual size)\n const outW = w;\n const outH = h;\n\n const naturalRect = { x: natX, y: natY, width: natW, height: natH };\n const canvas = await drawCropToCanvas(img, naturalRect, outW, outH);\n\n if (!canvas) {\n // Cross-origin failure — inform user and abort\n window.alert(\n 'Cannot crop this image: the image server does not allow cross-origin access.\\n' +\n 'Upload the image directly to use the crop tool.',\n );\n this._close(false);\n return;\n }\n\n // Determine output format: preserve JPEG, fall back to PNG\n const fmt = img.src.match(/^data:image\\/(jpe?g)/i) ? 'image/jpeg' : 'image/png';\n const quality = fmt === 'image/jpeg' ? 0.92 : undefined;\n const newSrc = canvas.toDataURL(fmt, quality);\n\n // Apply the crop\n this._close(false);\n\n img.src = newSrc;\n // Strip explicit width/height — the image should show at its new natural size\n img.style.width = '';\n img.style.height = '';\n img.removeAttribute('width');\n img.removeAttribute('height');\n\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n }\n\n /**\n * Remove all overlay DOM elements and reset state.\n * @param {boolean} _committed - reserved for future use\n */\n _close(_committed) {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n [this._scrim, this._cropBox, this._toolbar].forEach((el) => {\n if (el && el.parentNode) el.parentNode.removeChild(el);\n });\n\n this._scrim = null;\n this._cropBox = null;\n this._toolbar = null;\n this._infoEl = null;\n this._handles = {};\n this._img = null;\n this._box = null;\n this._imgRect = null;\n this._arCheck = null;\n }\n}\n","/**\n * Context.js - Central hub for the editor instance\n * Holds references to all sub-modules and manages inter-module communication.\n * Inspired by Summernote's Context.js\n */\n\nimport { mergeDeep } from './core/func.js';\nimport { defaultOptions } from './settings.js';\nimport { resolveLocale } from './i18n/index.js';\nimport { renderLayout } from './renderer.js';\nimport { on } from './core/dom.js';\n\n// Modules\nimport { Editor } from './module/Editor.js';\nimport { Toolbar } from './module/Toolbar.js';\nimport { Statusbar } from './module/Statusbar.js';\nimport { Clipboard } from './module/Clipboard.js';\nimport { Placeholder } from './module/Placeholder.js';\nimport { Codeview } from './module/Codeview.js';\nimport { Fullscreen } from './module/Fullscreen.js';\nimport { LinkDialog } from './module/LinkDialog.js';\nimport { ImageDialog } from './module/ImageDialog.js';\nimport { VideoDialog } from './module/VideoDialog.js';\nimport { ImageResizer } from './module/ImageResizer.js';\nimport { VideoResizer } from './module/VideoResizer.js';\nimport { LinkTooltip } from './module/LinkTooltip.js';\nimport { ImageTooltip } from './module/ImageTooltip.js';\nimport { VideoTooltip } from './module/VideoTooltip.js';\nimport { TableTooltip } from './module/TableTooltip.js';\nimport { CodeTooltip } from './module/CodeTooltip.js';\nimport { EmojiDialog } from './module/EmojiDialog.js';\nimport { IconDialog } from './module/IconDialog.js';\nimport { ContextMenu } from './module/ContextMenu.js';\nimport { ShortcutsDialog } from './module/ShortcutsDialog.js';\nimport { FindReplace } from './module/FindReplace.js';\nimport { ImageCropOverlay } from './module/ImageCropOverlay.js';\n\n/** Module registry shared across all Context instances (populated via AutumnNote.registerModule). */\nexport const _customModules = new Map();\n\nexport class Context {\n /**\n * @param {HTMLElement} targetEl - The element to replace with the editor\n * @param {import('./settings.js').AsnOptions} [userOptions]\n */\n constructor(targetEl, userOptions = {}) {\n this.targetEl = targetEl;\n this.options = mergeDeep(defaultOptions, userOptions);\n\n /** @type {import('./i18n/index.js').AsnLocale} */\n this.locale = resolveLocale(this.options.lang);\n\n /** @type {{ container: HTMLElement, editable: HTMLElement, toolbar?: HTMLElement, statusbar?: HTMLElement }} */\n this.layoutInfo = {};\n\n /** @type {Map<string, Function[]>} */\n this._listeners = new Map();\n\n /** @type {Map<string, object>} */\n this._modules = new Map();\n\n this._disposers = [];\n this._alive = false;\n }\n\n // ---------------------------------------------------------------------------\n // Initialisation\n // ---------------------------------------------------------------------------\n\n initialize() {\n // 1. Render the DOM skeleton\n const { container, editable } = renderLayout(this.targetEl, this.options);\n this.layoutInfo.container = container;\n this.layoutInfo.editable = editable;\n\n // 2. Register core modules\n this._registerModules();\n\n // 3. Attach toolbar/statusbar to container\n const toolbar = this._modules.get('toolbar');\n if (toolbar && toolbar.el) {\n container.insertBefore(toolbar.el, editable);\n this.layoutInfo.toolbar = toolbar.el;\n }\n\n const statusbar = this._modules.get('statusbar');\n if (statusbar && statusbar.el) {\n container.appendChild(statusbar.el);\n this.layoutInfo.statusbar = statusbar.el;\n }\n\n // 4. Bind editor-level events\n this._bindEditorEvents(editable);\n\n // 5. Auto-focus if requested\n if (this.options.focus) {\n editable.focus();\n }\n\n this._alive = true;\n\n // Initial toolbar sync so dropdowns show the correct font on load\n this.invoke('toolbar.refresh');\n\n if (typeof this.options.onInit === 'function') {\n this.options.onInit(this);\n }\n\n return this;\n }\n\n _registerModules() {\n const register = (name, ModuleClass) => {\n const instance = new ModuleClass(this);\n this._modules.set(name, instance);\n instance.initialize();\n };\n\n register('editor', Editor);\n register('toolbar', Toolbar);\n register('statusbar', Statusbar);\n register('clipboard', Clipboard);\n register('contextMenu', ContextMenu);\n register('placeholder', Placeholder);\n register('codeview', Codeview);\n register('fullscreen', Fullscreen);\n register('linkDialog', LinkDialog);\n register('imageDialog', ImageDialog);\n register('videoDialog', VideoDialog);\n register('imageResizer', ImageResizer);\n register('videoResizer', VideoResizer);\n register('linkTooltip', LinkTooltip);\n register('imageTooltip', ImageTooltip);\n register('videoTooltip', VideoTooltip);\n register('tableTooltip', TableTooltip);\n register('codeTooltip', CodeTooltip);\n register('emojiDialog', EmojiDialog);\n register('iconDialog', IconDialog);\n register('shortcutsDialog', ShortcutsDialog);\n register('findReplace', FindReplace);\n register('imageCropOverlay', ImageCropOverlay);\n\n // Custom modules registered via AutumnNote.registerModule()\n for (const [name, ModuleClass] of _customModules) {\n register(name, ModuleClass);\n }\n }\n\n /**\n * Registers and initialises a custom module on this instance.\n * @param {string} name\n * @param {Function} ModuleClass\n * @returns {this}\n */\n registerModule(name, ModuleClass) {\n if (this._modules.has(name)) return this;\n const instance = new ModuleClass(this);\n instance.initialize();\n this._modules.set(name, instance);\n return this;\n }\n\n _bindEditorEvents(editable) {\n // Keep the original textarea/input value in sync immediately on every input.\n // This guarantees form.submit() sees fresh data even before debounced change.\n const d0 = on(editable, 'input', () => this._syncToTarget());\n const d1 = on(editable, 'focus', () => {\n this.layoutInfo.container.classList.add('an-focused');\n if (typeof this.options.onFocus === 'function') {\n this.options.onFocus(this);\n }\n });\n const d2 = on(editable, 'blur', () => {\n this.layoutInfo.container.classList.remove('an-focused');\n this._syncToTarget();\n if (typeof this.options.onBlur === 'function') {\n this.options.onBlur(this);\n }\n });\n // Sync textarea/input value on every change so form.submit() always gets fresh content\n const d3 = this.on('change', () => this._syncToTarget());\n this._disposers.push(d0, d1, d2, d3);\n\n // Auto-save to localStorage on every change\n if (this.options.autoSave && this.options.autoSaveKey) {\n const d4 = this.on('change', () => {\n try { localStorage.setItem(this.options.autoSaveKey, this.getHTML()); } catch (_) {}\n });\n this._disposers.push(d4);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Module invocation\n // ---------------------------------------------------------------------------\n\n /**\n * Invokes a method on a registered module.\n * Format: 'moduleName.methodName'\n * @param {string} path - e.g. 'editor.bold'\n * @param {...*} args\n * @returns {*}\n */\n invoke(path, ...args) {\n const [moduleName, methodName] = path.split('.');\n const module = this._modules.get(moduleName);\n if (!module) {\n console.warn(`[AutumnNote] invoke: module \"${moduleName}\" not found (path: \"${path}\")`);\n return undefined;\n }\n if (typeof module[methodName] !== 'function') {\n console.warn(`[AutumnNote] invoke: method \"${methodName}\" not found on module \"${moduleName}\" (path: \"${path}\")`);\n return undefined;\n }\n return module[methodName](...args);\n }\n\n // ---------------------------------------------------------------------------\n // Event system\n // ---------------------------------------------------------------------------\n\n /**\n * Subscribes to an editor event.\n * @param {string} eventName\n * @param {Function} handler\n * @returns {() => void} unsubscribe\n */\n on(eventName, handler) {\n if (!this._listeners.has(eventName)) {\n this._listeners.set(eventName, []);\n }\n this._listeners.get(eventName).push(handler);\n return () => this.off(eventName, handler);\n }\n\n /**\n * Unsubscribes from an editor event.\n * @param {string} eventName\n * @param {Function} handler\n */\n off(eventName, handler) {\n const handlers = this._listeners.get(eventName);\n if (!handlers) return;\n const idx = handlers.indexOf(handler);\n if (idx !== -1) handlers.splice(idx, 1);\n }\n\n /**\n * Triggers an editor event.\n * @param {string} eventName\n * @param {...*} args\n */\n triggerEvent(eventName, ...args) {\n const handlers = this._listeners.get(eventName) || [];\n handlers.forEach((h) => h(...args));\n\n // Also call options callback if present (e.g. onChange)\n const cbName = 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1);\n if (typeof this.options[cbName] === 'function') {\n this.options[cbName](...args);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public editor API\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the current HTML content of the editor.\n * @returns {string}\n */\n getHTML() {\n return this.invoke('editor.getHTML');\n }\n\n /**\n * Sets the HTML content of the editor.\n * @param {string} html\n */\n setHTML(html) {\n this.invoke('editor.setHTML', html);\n }\n\n /**\n * Returns the plain text content of the editor.\n * @returns {string}\n */\n getText() {\n return this.invoke('editor.getText');\n }\n\n /**\n * Sets the editor content as plain text (HTML-escaped).\n * @param {string} text\n */\n setText(text) {\n this.invoke('editor.setText', text);\n }\n\n /**\n * Clears the editor content.\n */\n clear() {\n this.invoke('editor.clear');\n }\n\n /**\n * Resets the undo/redo history stack.\n * Useful after programmatically loading a new document via setHTML() / setMarkdown()\n * so that Ctrl+Z cannot undo back to the previous document.\n */\n clearHistory() {\n this.invoke('editor.clearHistory');\n }\n\n /**\n * Returns true when the editor has no meaningful content.\n * @returns {boolean}\n */\n isEmpty() {\n return this.invoke('editor.isEmpty');\n }\n\n /**\n * Inserts HTML at the current cursor position.\n * @param {string} html\n */\n insertHTML(html) {\n this.invoke('editor.insertHTML', html);\n }\n\n /**\n * Inserts plain text at the current cursor position.\n * @param {string} text\n */\n insertText(text) {\n this.invoke('editor.insertText', text);\n }\n\n /**\n * Sets editor content from a Markdown string.\n * @param {string} md\n */\n setMarkdown(md) {\n this.invoke('editor.setMarkdown', md);\n }\n\n /**\n * Returns the editor content as Markdown.\n * @returns {string}\n */\n getMarkdown() {\n return this.invoke('editor.getMarkdown');\n }\n\n /**\n * Returns the current word count of the editor content.\n * @returns {number}\n */\n getWordCount() {\n return this.invoke('statusbar.getWordCount') ?? 0;\n }\n\n /**\n * Returns the current character count of the editor content.\n * @returns {number}\n */\n getCharCount() {\n return this.invoke('statusbar.getCharCount') ?? 0;\n }\n\n /**\n * Downloads the editor content as an HTML file.\n * @param {string} [filename='document.html']\n */\n downloadHTML(filename = 'document.html') {\n this._download(this.getHTML(), filename, 'text/html');\n }\n\n /**\n * Downloads the editor content as a plain-text file.\n * @param {string} [filename='document.txt']\n */\n downloadText(filename = 'document.txt') {\n this._download(this.getText(), filename, 'text/plain');\n }\n\n /**\n * Downloads the editor content as a Markdown file.\n * @param {string} [filename='document.md']\n */\n downloadMarkdown(filename = 'document.md') {\n this._download(this.getMarkdown(), filename, 'text/markdown');\n }\n\n /**\n * Creates a temporary Blob URL and triggers a browser file download.\n * @param {string} content\n * @param {string} filename\n * @param {string} mimeType\n */\n _download(content, filename, mimeType) {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }\n\n /**\n * Opens the editor content in a new window and triggers the browser print dialog.\n * @param {string} [title='']\n */\n print(title = '') {\n const content = this.getHTML();\n const safeTitle = (title || '').replace(/</g, '<').replace(/>/g, '>');\n const w = window.open('', '_blank');\n if (!w) return; // popup blocked by browser\n w.document.write(\n '<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\">' +\n `<title>${safeTitle}</title>` +\n '<style>' +\n 'body{font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,Arial,sans-serif;font-size:14px;line-height:1.6;padding:20mm;color:#111827;}' +\n 'ul.an-checklist{list-style:none;padding-left:0;}' +\n 'ul.an-checklist li{padding-left:24px;position:relative;margin:2px 0;}' +\n 'ul.an-checklist li input[type=\"checkbox\"]{position:absolute;left:0;top:3px;}' +\n 'code{background:#f3f4f6;border-radius:3px;padding:.1em .35em;font-family:monospace;}' +\n 'pre{background:#f3f4f6;padding:.75em 1em;border-radius:4px;overflow-x:auto;}' +\n 'table{border-collapse:collapse;}td,th{border:1px solid #d1d5db;padding:4px 8px;}' +\n '</style>' +\n `</head><body>${content}</body></html>`,\n );\n w.document.close();\n w.onload = () => { w.print(); };\n }\n\n /**\n * Sets whether the editor is disabled (readonly).\n * @param {boolean} disabled\n */\n setDisabled(disabled) {\n const editable = this.layoutInfo.editable;\n if (disabled) {\n editable.setAttribute('contenteditable', 'false');\n this.layoutInfo.container.classList.add('an-disabled');\n editable.querySelectorAll('ul.an-checklist input[type=\"checkbox\"]').forEach((cb) => {\n cb.setAttribute('disabled', '');\n });\n } else {\n editable.setAttribute('contenteditable', 'true');\n this.layoutInfo.container.classList.remove('an-disabled');\n editable.querySelectorAll('ul.an-checklist input[type=\"checkbox\"]').forEach((cb) => {\n cb.removeAttribute('disabled');\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // Destroy\n // ---------------------------------------------------------------------------\n\n /**\n * Completely removes the editor and restores the original element.\n */\n destroy() {\n if (!this._alive) return;\n\n this._modules.forEach((module) => {\n if (typeof module.destroy === 'function') module.destroy();\n });\n this._modules.clear();\n\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n const container = this.layoutInfo.container;\n if (container && container.parentNode) {\n // Restore original element\n this.targetEl.style.display = '';\n container.parentNode.removeChild(container);\n }\n\n if (typeof this.options.onDestroy === 'function') {\n this.options.onDestroy(this);\n }\n\n this._alive = false;\n this._listeners.clear();\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Syncs editor HTML back into the original textarea/input for form submission.\n */\n _syncToTarget() {\n if (this.targetEl.tagName === 'TEXTAREA' || this.targetEl.tagName === 'INPUT') {\n this.targetEl.value = this.getHTML();\n }\n }\n}\n","/**\n * lists.js - Array/list utility helpers\n * Inspired by Summernote's lists.js\n */\n\n/**\n * Returns the last element of an array.\n * @template T\n * @param {T[]} arr\n * @returns {T|undefined}\n */\nexport function last(arr) {\n return arr[arr.length - 1];\n}\n\n/**\n * Returns the first element of an array.\n * @template T\n * @param {T[]} arr\n * @returns {T|undefined}\n */\nexport function first(arr) {\n return arr[0];\n}\n\n/**\n * Returns a new array without the last n items.\n * @template T\n * @param {T[]} arr\n * @param {number} [n=1]\n * @returns {T[]}\n */\nexport function initial(arr, n = 1) {\n return arr.slice(0, arr.length - n);\n}\n\n/**\n * Returns a new array without the first n items.\n * @template T\n * @param {T[]} arr\n * @param {number} [n=1]\n * @returns {T[]}\n */\nexport function tail(arr, n = 1) {\n return arr.slice(n);\n}\n\n/**\n * Returns a flattened (one level) array.\n * @template T\n * @param {T[][]} arr\n * @returns {T[]}\n */\nexport function flatten(arr) {\n return arr.reduce((acc, val) => acc.concat(val), []);\n}\n\n/**\n * Returns unique elements of an array (using Set).\n * @template T\n * @param {T[]} arr\n * @returns {T[]}\n */\nexport function unique(arr) {\n return [...new Set(arr)];\n}\n\n/**\n * Splits an array into chunks of size n.\n * @template T\n * @param {T[]} arr\n * @param {number} n\n * @returns {T[][]}\n */\nexport function chunk(arr, n) {\n const result = [];\n for (let i = 0; i < arr.length; i += n) {\n result.push(arr.slice(i, i + n));\n }\n return result;\n}\n\n/**\n * Groups array elements by a key function.\n * @template T\n * @param {T[]} arr\n * @param {(item: T) => string} keyFn\n * @returns {Record<string, T[]>}\n */\nexport function groupBy(arr, keyFn) {\n return arr.reduce((groups, item) => {\n const key = keyFn(item);\n if (!groups[key]) {\n groups[key] = [];\n }\n groups[key].push(item);\n return groups;\n }, {});\n}\n\n/**\n * Returns true if all elements satisfy the predicate.\n * @template T\n * @param {T[]} arr\n * @param {(item: T) => boolean} predicate\n * @returns {boolean}\n */\nexport function all(arr, predicate) {\n return arr.every(predicate);\n}\n\n/**\n * Returns true if any element satisfies the predicate.\n * @template T\n * @param {T[]} arr\n * @param {(item: T) => boolean} predicate\n * @returns {boolean}\n */\nexport function any(arr, predicate) {\n return arr.some(predicate);\n}\n","/**\n * env.js - Environment / browser detection\n * Inspired by Summernote's env.js\n */\n\nconst userAgent = navigator.userAgent;\n\nexport const env = {\n /** True if browser is Chrome */\n isChrome: /Chrome\\//.test(userAgent),\n /** True if browser is Firefox */\n isFF: /Firefox\\//.test(userAgent),\n /** True if browser is Safari (not Chrome) */\n isSafari: /^((?!chrome|android).)*safari/i.test(userAgent),\n /** True if browser is Edge (Chromium) */\n isEdge: /Edg\\//.test(userAgent),\n /** True if running on macOS */\n isMac: /Macintosh/.test(userAgent),\n /** True if running on mobile */\n isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent),\n /** True if touch is supported */\n isTouch: 'ontouchstart' in window || navigator.maxTouchPoints > 0,\n /** Modifier key name depending on platform */\n modifierKey: /Macintosh/.test(userAgent) ? 'metaKey' : 'ctrlKey',\n};\n","/**\n * index.js - Public entry point for AutumnNote\n *\n * Usage (module):\n * import AutumnNote from 'autumnnote';\n * const editor = AutumnNote.create('#my-editor', { placeholder: 'Start typing…' });\n *\n * Usage (UMD / script tag):\n * const editor = AutumnNote.create('#my-editor');\n */\n\nimport '../styles/autumnnote.scss';\nimport { Context, _customModules } from './Context.js';\nimport { defaultOptions } from './settings.js';\n\n// Snapshot of factory defaults taken at module-load time (before any setDefaults() calls)\nconst _originalDefaults = { ...defaultOptions };\n\n// Re-export for tree-shaking / module consumers\nexport { Context } from './Context.js';\nexport { defaultOptions } from './settings.js';\nexport * from './core/dom.js';\nexport * from './core/range.js';\nexport * from './core/func.js';\nexport * from './core/key.js';\nexport * from './core/lists.js';\nexport * from './core/env.js';\nexport * from './core/sanitise.js';\nexport * from './module/Buttons.js';\nexport { locales, resolveLocale } from './i18n/index.js';\n\n// ---------------------------------------------------------------------------\n// Main factory\n// ---------------------------------------------------------------------------\n\n/** @type {WeakMap<Element, Context>} */\nconst instances = new WeakMap();\n\nconst AutumnNote = {\n /**\n * Creates (or returns existing) editor instance on one or more elements.\n *\n * @param {string|Element|NodeList|Element[]} selector\n * @param {import('./settings.js').AsnOptions} [options]\n * @returns {Context|Context[]} single Context or array of Contexts\n */\n create(selector, options = {}) {\n const elements = resolveElements(selector);\n const ctxs = elements.map((el) => {\n if (instances.has(el)) return instances.get(el);\n const ctx = new Context(el, options);\n ctx.initialize();\n instances.set(el, ctx);\n return ctx;\n });\n return ctxs.length === 1 ? ctxs[0] : ctxs;\n },\n\n /**\n * Destroys the editor(s) on the given selector.\n * @param {string|Element|NodeList|Element[]} selector\n */\n destroy(selector) {\n resolveElements(selector).forEach((el) => {\n const ctx = instances.get(el);\n if (ctx) {\n ctx.destroy();\n instances.delete(el);\n }\n });\n },\n\n /**\n * Returns the Context instance for a given element (or null).\n * @param {string|Element} selector\n * @returns {Context|null}\n */\n getInstance(selector) {\n const el = typeof selector === 'string' ? document.querySelector(selector) : selector;\n return el ? instances.get(el) || null : null;\n },\n\n /** Returns a shallow copy of the default options (read-only snapshot). */\n get defaults() { return { ...defaultOptions }; },\n\n /** Merges properties into the global defaults, applied to all future instances. */\n setDefaults(overrides) { Object.assign(defaultOptions, overrides); },\n\n /** Restores global defaults to their original factory values. */\n resetDefaults() {\n Object.keys(defaultOptions).forEach((k) => delete defaultOptions[k]);\n Object.assign(defaultOptions, _originalDefaults);\n },\n\n /**\n * Registers a custom module to be included in every new editor instance.\n * @param {string} name - unique module key used for ctx.invoke() calls\n * @param {Function} ModuleClass - class with initialize() and optional destroy()\n */\n registerModule(name, ModuleClass) { _customModules.set(name, ModuleClass); },\n\n /** Library version */\n version: '1.0.9',\n};\n\n// ---------------------------------------------------------------------------\n// Helper\n// ---------------------------------------------------------------------------\n\n/**\n * @param {string|Element|NodeList|Element[]} selector\n * @returns {Element[]}\n */\nfunction resolveElements(selector) {\n if (typeof selector === 'string') {\n return Array.from(document.querySelectorAll(selector));\n }\n if (selector instanceof Element) {\n return [selector];\n }\n if (selector instanceof NodeList || Array.isArray(selector)) {\n return Array.from(selector);\n }\n return [];\n}\n\nexport default AutumnNote;\n"],"mappings":"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C;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CAGnD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAK;EAAkC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAiC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAK;EAAkC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAO;EAAiC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAiC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAGlD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CAGnD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAK;EAAkC;EAAO;CAC/C;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO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AAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAK;EAAkC;EAAU;CAClD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAK;EAAkC;EAAU;CAClD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CAGnD;EAAC;EAAK;EAAkC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAkC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAK;EAAiC;EAAU;CACjD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAM;EAAiC;EAAU;CAClD;EAAC;EAAK;EAAi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"}
|
|
1
|
+
{"version":3,"file":"autumnnote.es.js","names":["Style.bold","Style.italic","Style.underline","Style.strikethrough","Style.superscript","Style.subscript","Style.justifyLeft","Style.justifyCenter","Style.justifyRight","Style.justifyFull","Style.insertUnorderedList","Style.insertOrderedList","Style.indent","Style.outdent","Style.execCommand","Style.fontSize","Style.fontName","Style.formatBlock","Style.lineHeight","Style.isInlineCode","Style.isInChecklist","Style.foreColor","Style.backColor","_S","HANDLE_DEFS","ICONS","SHOW_DELAY","HIDE_DELAY","ICONS","SHOW_DELAY","HIDE_DELAY","ICONS","SHOW_DELAY","HIDE_DELAY","SHOW_DELAY","HIDE_DELAY","ICONS","ICONS","clamp"],"sources":["../src/js/core/func.js","../src/js/core/dom.js","../src/js/core/range.js","../src/js/editing/Style.js","../src/js/module/Buttons.js","../src/js/settings.js","../src/js/i18n/en.js","../src/js/i18n/vi.js","../src/js/i18n/ja.js","../src/js/i18n/zh.js","../src/js/i18n/fr.js","../src/js/i18n/de.js","../src/js/i18n/es.js","../src/js/i18n/ko.js","../src/js/i18n/index.js","../src/js/core/sanitise.js","../src/js/renderer.js","../src/js/editing/History.js","../src/js/editing/Table.js","../src/js/core/key.js","../src/js/editing/Typing.js","../src/js/core/markdown.js","../src/js/module/Editor.js","../src/js/module/Toolbar.js","../src/js/module/Statusbar.js","../src/js/module/Clipboard.js","../src/js/module/Placeholder.js","../src/js/module/Codeview.js","../src/js/module/Fullscreen.js","../src/js/module/LinkDialog.js","../src/js/module/ImageDialog.js","../src/js/module/VideoDialog.js","../src/js/module/ImageResizer.js","../src/js/module/VideoResizer.js","../src/js/module/LinkTooltip.js","../src/js/module/ImageTooltip.js","../src/js/module/VideoTooltip.js","../src/js/module/TableTooltip.js","../src/js/module/CodeTooltip.js","../src/js/module/EmojiDialog.js","../src/js/module/IconDialog.js","../src/js/module/ContextMenu.js","../src/js/module/ShortcutsDialog.js","../src/js/module/FindReplace.js","../src/js/module/ImageCropOverlay.js","../src/js/module/AutoSaveRestore.js","../src/js/module/MarkdownShortcuts.js","../src/js/module/BubbleToolbar.js","../src/js/module/Mention.js","../src/js/Context.js","../src/js/core/lists.js","../src/js/core/env.js","../src/js/index.js"],"sourcesContent":["/**\n * func.js - General utility / functional helpers\n * Inspired by Summernote's func.js\n */\n\n/**\n * Clamp a value between min and max.\n * @param {number} val\n * @param {number} min\n * @param {number} max\n * @returns {number}\n */\nexport function clamp(val, min, max) {\n return Math.min(Math.max(val, min), max);\n}\n\n/**\n * Debounce a function call.\n * @param {Function} fn\n * @param {number} delay - milliseconds\n * @returns {Function}\n */\nexport function debounce(fn, delay) {\n let timer;\n return function (...args) {\n clearTimeout(timer);\n timer = setTimeout(() => fn.apply(this, args), delay);\n };\n}\n\n/**\n * Throttle a function call.\n * @param {Function} fn\n * @param {number} limit - milliseconds\n * @returns {Function}\n */\nexport function throttle(fn, limit) {\n let lastCall = 0;\n return function (...args) {\n const now = Date.now();\n if (now - lastCall >= limit) {\n lastCall = now;\n return fn.apply(this, args);\n }\n };\n}\n\n/**\n * Compose multiple functions right-to-left.\n * @param {...Function} fns\n * @returns {Function}\n */\nexport function compose(...fns) {\n return (x) => fns.reduceRight((v, f) => f(v), x);\n}\n\n/**\n * Identity function.\n * @template T\n * @param {T} x\n * @returns {T}\n */\nexport function identity(x) {\n return x;\n}\n\n/**\n * Determines if a value is null or undefined.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isNil(val) {\n return val === null || val === undefined;\n}\n\n/**\n * Determines if a value is a string.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determines if a value is a function.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isFunction(val) {\n return typeof val === 'function';\n}\n\n/**\n * Deep-merge two plain objects. Returns a new object.\n * Arrays are cloned (shallow copy) rather than shared by reference so that\n * mutations to the merged result do not bleed back into the source object\n * (e.g. mutating `instance.options.fontFamilies` should not affect\n * `AutumnNote.defaults.fontFamilies`).\n * @param {object} target\n * @param {object} source\n * @returns {object}\n */\nexport function mergeDeep(target, source) {\n // Start with a shallow copy of target; clone any arrays to avoid shared refs\n const output = {};\n for (const key of Object.keys(target)) {\n output[key] = Array.isArray(target[key]) ? [...target[key]] : target[key];\n }\n if (isPlainObject(target) && isPlainObject(source)) {\n for (const key of Object.keys(source)) {\n if (isPlainObject(source[key])) {\n // When target[key] is null / undefined / a non-object (e.g. the `mention: null`\n // default), merge into an empty object instead of passing null to the next\n // recursive call — which would silently drop all source properties.\n const base = isPlainObject(target[key]) ? target[key] : {};\n output[key] = mergeDeep(base, source[key]);\n } else if (Array.isArray(source[key])) {\n output[key] = [...source[key]];\n } else {\n output[key] = source[key];\n }\n }\n }\n return output;\n}\n\n/**\n * Checks if value is a plain object.\n * @param {*} val\n * @returns {boolean}\n */\nexport function isPlainObject(val) {\n return val !== null && typeof val === 'object' && !Array.isArray(val);\n}\n\n/**\n * Convert a DOMRect (or similar bounding object) to a plain object bounding box.\n * Guards against missing/null rect (e.g. in AirMode).\n * @param {DOMRect|null|undefined} rect\n * @returns {{ top: number, left: number, width: number, height: number, bottom: number, right: number }|null}\n */\nexport function rect2bnd(rect) {\n if (!rect) return null;\n return {\n top: Math.round(rect.top),\n left: Math.round(rect.left),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n bottom: Math.round(rect.bottom),\n right: Math.round(rect.right),\n };\n}\n","/**\n * dom.js - DOM manipulation utilities\n * Inspired by Summernote's dom.js — rewritten for vanilla JS without jQuery\n */\n\n// ---------------------------------------------------------------------------\n// Node type helpers\n// ---------------------------------------------------------------------------\n\nexport const ELEMENT_NODE = 1;\nexport const TEXT_NODE = 3;\n\n/** @param {Node} node */\nexport const isElement = (node) => node && node.nodeType === ELEMENT_NODE;\n/** @param {Node} node */\nexport const isText = (node) => node && node.nodeType === TEXT_NODE;\n/** @param {Node} node */\nexport const isVoid = (node) => isElement(node) && /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isPara = (node) => isElement(node) && /^(p|div|li|h[1-6]|blockquote|td|th|pre)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isLi = (node) => isElement(node) && /^(li)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isList = (node) => isElement(node) && /^(ul|ol)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isTable = (node) => isElement(node) && node.nodeName.toUpperCase() === 'TABLE';\n/** @param {Node} node */\nexport const isInline = (node) =>\n isElement(node) &&\n /^(a|abbr|acronym|b|bdo|big|br|button|cite|code|dfn|em|i|img|input|kbd|label|map|object|output|q|s|samp|select|small|span|strong|sub|sup|textarea|time|tt|u|var)$/i.test(node.nodeName);\n/** @param {Node} node */\nexport const isEditable = (node) => isElement(node) && node.isContentEditable;\n/** @param {Node} node */\nexport const isAnchor = (node) => isElement(node) && node.nodeName.toUpperCase() === 'A';\n/** @param {Node} node */\nexport const isImage = (node) => isElement(node) && node.nodeName.toUpperCase() === 'IMG';\n\n// ---------------------------------------------------------------------------\n// Tree traversal\n// ---------------------------------------------------------------------------\n\n/**\n * Walk up the DOM tree from node, returning the first element matching predicate (inclusive).\n * @param {Node} node\n * @param {(node: Node) => boolean} predicate\n * @param {Node} [stopAt] - stop traversal at this ancestor (exclusive)\n * @returns {Node|null}\n */\nexport function closest(node, predicate, stopAt) {\n let cur = node;\n while (cur && cur !== stopAt) {\n if (predicate(cur)) return cur;\n cur = cur.parentNode;\n }\n return null;\n}\n\n/**\n * Returns the nearest ancestor that is a paragraph-like block.\n * @param {Node} node\n * @param {Node} [editable]\n * @returns {Node|null}\n */\nexport function closestPara(node, editable) {\n return closest(node, isPara, editable);\n}\n\n/**\n * Returns all ancestors of node up to (but not including) stopAt.\n * @param {Node} node\n * @param {Node} [stopAt]\n * @returns {Node[]}\n */\nexport function ancestors(node, stopAt) {\n const result = [];\n let cur = node.parentNode;\n while (cur && cur !== stopAt) {\n result.push(cur);\n cur = cur.parentNode;\n }\n return result;\n}\n\n/**\n * Returns all children of node as an Array.\n * @param {Node} node\n * @returns {Node[]}\n */\nexport function children(node) {\n return Array.from(node.childNodes);\n}\n\n/**\n * Returns the previous sibling element (skipping text/comment nodes).\n * @param {Node} node\n * @returns {Element|null}\n */\nexport function prevElement(node) {\n let sibling = node.previousSibling;\n while (sibling && !isElement(sibling)) {\n sibling = sibling.previousSibling;\n }\n return sibling;\n}\n\n/**\n * Returns the next sibling element.\n * @param {Node} node\n * @returns {Element|null}\n */\nexport function nextElement(node) {\n let sibling = node.nextSibling;\n while (sibling && !isElement(sibling)) {\n sibling = sibling.nextSibling;\n }\n return sibling;\n}\n\n// ---------------------------------------------------------------------------\n// DOM mutation helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an element with optional attributes and children.\n * @param {string} tag\n * @param {Record<string, string>} [attrs]\n * @param {(Node|string)[]} [childNodes]\n * @returns {HTMLElement}\n */\nexport function createElement(tag, attrs = {}, childNodes = []) {\n const el = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n el.setAttribute(k, v);\n }\n for (const child of childNodes) {\n if (typeof child === 'string') {\n el.appendChild(document.createTextNode(child));\n } else {\n el.appendChild(child);\n }\n }\n return el;\n}\n\n/**\n * Removes a node from its parent.\n * @param {Node} node\n */\nexport function remove(node) {\n if (node && node.parentNode) {\n node.parentNode.removeChild(node);\n }\n}\n\n/**\n * Unwraps a node — replaces the node with its children.\n * @param {Node} node\n */\nexport function unwrap(node) {\n const parent = node.parentNode;\n if (!parent) return;\n while (node.firstChild) {\n parent.insertBefore(node.firstChild, node);\n }\n parent.removeChild(node);\n}\n\n/**\n * Wraps a node with a wrapper element.\n * @param {Node} node\n * @param {HTMLElement} wrapper\n * @returns {HTMLElement} the wrapper\n */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Insert node after reference node.\n * @param {Node} newNode\n * @param {Node} refNode\n */\nexport function insertAfter(newNode, refNode) {\n if (refNode.nextSibling) {\n refNode.parentNode.insertBefore(newNode, refNode.nextSibling);\n } else {\n refNode.parentNode.appendChild(newNode);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Content helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the text content of a node (safe).\n * @param {Node} node\n * @returns {string}\n */\nexport function nodeValue(node) {\n return isText(node) ? node.nodeValue : node.textContent || '';\n}\n\n/**\n * Returns true if a node is empty (no visible content).\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isEmpty(node) {\n if (isText(node)) return !node.nodeValue;\n if (isVoid(node)) return false;\n return !node.textContent.trim() && !node.querySelector('img, video, hr, table');\n}\n\n/**\n * Returns the outerHTML of an element.\n * @param {Element} el\n * @returns {string}\n */\nexport function outerHtml(el) {\n return el.outerHTML;\n}\n\n// ---------------------------------------------------------------------------\n// Selection / editing helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Places the caret at the end of a contenteditable element.\n * @param {HTMLElement} el\n */\nexport function placeCaret(el) {\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n }\n}\n\n/**\n * Returns true if the node is inside a contenteditable root.\n * @param {Node} node\n * @returns {boolean}\n */\nexport function isInsideEditable(node) {\n return !!closest(node, isEditable);\n}\n\n// ---------------------------------------------------------------------------\n// Event helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Adds an event listener and returns a disposer function.\n * @param {EventTarget} target\n * @param {string} type\n * @param {EventListener} handler\n * @param {AddEventListenerOptions} [options]\n * @returns {() => void} disposer\n */\nexport function on(target, type, handler, options) {\n target.addEventListener(type, handler, options);\n return () => target.removeEventListener(type, handler, options);\n}\n\n/**\n * Installs a keyboard focus trap inside a dialog container.\n * - Tab / Shift+Tab cycles focus within the container's focusable children.\n * - Escape calls `onEscape` and removes the trap listener.\n *\n * Returns a disposer function that removes the listener (call on dialog close).\n *\n * @param {HTMLElement} container - the dialog element to trap focus inside\n * @param {() => void} onEscape - called when Escape is pressed\n * @returns {() => void} disposer\n */\nexport function trapFocus(container, onEscape) {\n const FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n const getFocusable = () => Array.from(container.querySelectorAll(FOCUSABLE)).filter(\n (el) => !el.closest('[style*=\"display: none\"]') && !el.closest('[style*=\"display:none\"]'),\n );\n\n const handler = (e) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onEscape && onEscape();\n return;\n }\n if (e.key !== 'Tab') return;\n const els = getFocusable();\n if (!els.length) return;\n const first = els[0];\n const last = els[els.length - 1];\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n}\n","/**\n * range.js - Selection and Range utilities\n * Inspired by Summernote's range.js — rewritten as vanilla JS\n */\n\nimport { isElement, closest } from './dom.js';\n\n// ---------------------------------------------------------------------------\n// WrappedRange — a convenience wrapper over the native Range API\n// ---------------------------------------------------------------------------\n\nexport class WrappedRange {\n /**\n * @param {Node} sc - start container\n * @param {number} so - start offset\n * @param {Node} ec - end container\n * @param {number} eo - end offset\n */\n constructor(sc, so, ec, eo) {\n this.sc = sc;\n this.so = so;\n this.ec = ec;\n this.eo = eo;\n }\n\n /** @returns {boolean} */\n isCollapsed() {\n return this.sc === this.ec && this.so === this.eo;\n }\n\n /** @returns {Range} */\n toNativeRange() {\n const range = document.createRange();\n try {\n range.setStart(this.sc, this.so);\n range.setEnd(this.ec, this.eo);\n } catch (_e) {\n // Guard against detached nodes\n }\n return range;\n }\n\n /**\n * Select this wrapped range in the window.\n */\n select() {\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(this.toNativeRange());\n }\n\n /**\n * Returns the common ancestor element of this range.\n * @returns {Element|null}\n */\n commonAncestor() {\n const native = this.toNativeRange();\n const ancestor = native.commonAncestorContainer;\n return isElement(ancestor) ? ancestor : ancestor.parentElement;\n }\n\n /**\n * Returns the nearest paragraph/block ancestor within the editable area.\n * @param {HTMLElement} editable\n * @returns {Element|null}\n */\n blockNode(editable) {\n return closest(this.sc, (n) => isElement(n) && n !== editable, editable);\n }\n\n /**\n * Returns either the selected text string or empty string.\n * @returns {string}\n */\n toString() {\n return this.toNativeRange().toString();\n }\n\n /**\n * Returns the bounding DOMRect of the range (or null).\n * @returns {DOMRect|null}\n */\n getClientRects() {\n const rects = this.toNativeRange().getClientRects();\n return rects.length > 0 ? rects[rects.length - 1] : null;\n }\n\n /**\n * Inserts a node at the start of this range.\n * @param {Node} node\n */\n insertNode(node) {\n const native = this.toNativeRange();\n native.insertNode(node);\n }\n\n}\n\n// ---------------------------------------------------------------------------\n// Factory helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a WrappedRange from a native Range object.\n * @param {Range} range\n * @returns {WrappedRange}\n */\nexport function fromNativeRange(range) {\n return new WrappedRange(\n range.startContainer,\n range.startOffset,\n range.endContainer,\n range.endOffset,\n );\n}\n\n/**\n * Returns a WrappedRange for the current window selection,\n * optionally restricted to a given editable element.\n * @param {HTMLElement} [editable]\n * @returns {WrappedRange|null}\n */\nexport function currentRange(editable) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const native = sel.getRangeAt(0);\n // Optionally check that the selection is inside the editable element\n if (editable && !editable.contains(native.commonAncestorContainer)) {\n return null;\n }\n return fromNativeRange(native);\n}\n\n/**\n * Creates a WrappedRange that covers the entire content of an element.\n * @param {HTMLElement} el\n * @returns {WrappedRange}\n */\nexport function rangeFromElement(el) {\n return new WrappedRange(el, 0, el, el.childNodes.length);\n}\n\n/**\n * Creates a collapsed range (cursor) at the given node / offset.\n * @param {Node} node\n * @param {number} offset\n * @returns {WrappedRange}\n */\nexport function collapsedRange(node, offset = 0) {\n return new WrappedRange(node, offset, node, offset);\n}\n\n// ---------------------------------------------------------------------------\n// Utility helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns true if the current selection is inside the given element.\n * @param {HTMLElement} el\n * @returns {boolean}\n */\nexport function isSelectionInside(el) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return false;\n return el.contains(sel.getRangeAt(0).commonAncestorContainer);\n}\n\n/**\n * Saves the current selection, executes fn, then restores the selection.\n * @param {Function} fn\n */\nexport function withSavedRange(fn) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) {\n fn(null);\n return;\n }\n const saved = sel.getRangeAt(0).cloneRange();\n fn(fromNativeRange(saved));\n sel.removeAllRanges();\n sel.addRange(saved);\n}\n\n/**\n * Splits the text node at the given offset and returns the two halves.\n * @param {Text} textNode\n * @param {number} offset\n * @returns {[Text, Text]}\n */\nexport function splitText(textNode, offset) {\n const after = textNode.splitText(offset);\n return [textNode, after];\n}\n","/**\n * Style.js - Inline / block style detection and application utilities\n * Rewritten from Summernote's approach using vanilla JS + execCommand fallback\n */\n\nimport { closest, isElement, isPara } from '../core/dom.js';\nimport { currentRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// execCommand wrappers (still the most compatible way in contenteditable)\n// ---------------------------------------------------------------------------\n\n/**\n * Applies a document execCommand.\n * @param {string} cmd\n * @param {string} [value]\n * @returns {boolean}\n */\nexport function execCommand(cmd, value = null) {\n return document.execCommand(cmd, false, value);\n}\n\n// ---------------------------------------------------------------------------\n// Inline style helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Bolds / unbolds the selection.\n */\nexport const bold = () => execCommand('bold');\n\n/**\n * Italicises / un-italicises the selection.\n */\nexport const italic = () => execCommand('italic');\n\n/**\n * Underlines / un-underlines the selection.\n * Falls back to manual DOM manipulation when inside <code> where\n * execCommand's state detection is unreliable.\n */\nexport function underline() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n // Check if we're inside a <u> (DOM truth), to guard against unreliable queryCommandState\n const uEl = container && container.closest && container.closest('u');\n const nativeState = document.queryCommandState('underline');\n if (uEl && !nativeState) {\n // Browser doesn't recognise the underline state (e.g. inside <code>).\n // Manually unwrap the <u> element.\n const parent = uEl.parentNode;\n while (uEl.firstChild) parent.insertBefore(uEl.firstChild, uEl);\n parent.removeChild(uEl);\n return;\n }\n execCommand('underline');\n}\n\n/**\n * Strikethrough / removes strikethrough.\n * Falls back to manual DOM manipulation inside nested formats where\n * execCommand's state detection is unreliable (mirrors underline() logic).\n */\nexport function strikethrough() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n // Use startContainer for consistent detection across collapsed and range\n // selections — commonAncestorContainer can miss ancestor <s>/<strike> tags\n // when the selection spans across nested inline elements.\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n const sEl = sc && sc.closest && (sc.closest('s') || sc.closest('strike'));\n const nativeState = document.queryCommandState('strikeThrough');\n if (sEl && !nativeState) {\n // Browser doesn’t recognise the strikethrough state (e.g. inside <code>\n // or deeply nested inline formats). Manually unwrap the <s>/<strike>.\n const parent = sEl.parentNode;\n while (sEl.firstChild) parent.insertBefore(sEl.firstChild, sEl);\n parent.removeChild(sEl);\n return;\n }\n execCommand('strikeThrough');\n}\n\n/**\n * Superscript toggle.\n */\nexport const superscript = () => execCommand('superscript');\n\n/**\n * Subscript toggle.\n */\nexport const subscript = () => execCommand('subscript');\n\n/**\n * Sets the foreground colour of the selected text.\n * @param {string} color - CSS colour string\n */\nexport const foreColor = (color) => execCommand('foreColor', color);\n\n/**\n * Sets the background (highlight) colour of the selected text.\n * @param {string} color - CSS colour string\n */\nexport const backColor = (color) => execCommand('hiliteColor', color);\n\n/**\n * Sets the font name for the selection.\n * @param {string} name\n */\nexport const fontName = (name) => execCommand('fontName', name);\n\n/**\n * Sets the font size (in pt or with unit) for the selection.\n * Uses a span-based approach to set px sizes precisely.\n * @param {string} size - e.g. '14px'\n * @param {HTMLElement} [editable] - scoping element to avoid touching nodes outside this editor\n */\nexport function fontSize(size, editable = document) {\n const sel = window.getSelection();\n const wasCollapsed = !sel || !sel.rangeCount || sel.getRangeAt(0).collapsed;\n\n // B-I-3/4: For a collapsed (caret) selection the browser's execCommand\n // 'fontSize' leaves an internal \"pending\" state of size-7 (=48px) instead of\n // creating a <font> element, so the very next typed character comes out at\n // 48px. Fix: bypass execCommand entirely for collapsed selections and directly\n // insert a span with the requested size, placing the cursor inside it.\n // Only applies when there IS an active selection (sel.rangeCount > 0); when\n // there is no selection at all (e.g. jsdom unit tests) fall through to the\n // execCommand path so the font-replacement logic still runs.\n if (wasCollapsed && sel && sel.rangeCount > 0) {\n try {\n const range = sel.getRangeAt(0);\n const span = document.createElement('span');\n span.style.fontSize = size;\n const zwsNode = document.createTextNode('\\u200B');\n span.appendChild(zwsNode);\n range.insertNode(span);\n const nr = document.createRange();\n nr.setStart(zwsNode, zwsNode.textContent.length);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n } catch (_) { /* ignore range errors on unusual DOM structures */ }\n return;\n }\n\n // Non-collapsed selection (or no selection — handles jsdom test setup where\n // <font size=\"7\"> elements are injected directly without a live selection):\n // use execCommand placeholder approach then replace <font> with <span>.\n execCommand('fontSize', '7');\n const scope = editable instanceof HTMLElement ? editable : document;\n const newSpans = [];\n scope.querySelectorAll('font[size=\"7\"]').forEach((el) => {\n const span = document.createElement('span');\n span.style.fontSize = size;\n el.parentNode.insertBefore(span, el);\n while (el.firstChild) span.appendChild(el.firstChild);\n el.parentNode.removeChild(el);\n newSpans.push(span);\n });\n\n // Re-select all replaced content so toolbar getValue() reads the new size\n // (B-I-1/2: without this re-selection the toolbar dropdown stays on the old\n // value until the next selectionchange event).\n if (!wasCollapsed && sel && newSpans.length > 0) {\n const first = newSpans[0];\n const last = newSpans[newSpans.length - 1];\n try {\n const nr = document.createRange();\n const startNode = first.firstChild || first;\n const endNode = last.lastChild || last;\n nr.setStart(startNode, 0);\n nr.setEnd(endNode, endNode.nodeType === Node.TEXT_NODE ? endNode.textContent.length : endNode.childNodes.length);\n sel.removeAllRanges();\n sel.addRange(nr);\n } catch (_) { /* ignore range errors on unusual DOM structures */ }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Block style helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps the selection in the given block tag (p, h1-h6, blockquote, pre).\n * @param {string} tagName\n */\nexport const formatBlock = (tagName) => execCommand('formatBlock', `<${tagName}>`);\n\n/**\n * Left-aligns the current block.\n */\nexport const justifyLeft = () => execCommand('justifyLeft');\n\n/**\n * Center-aligns the current block.\n */\nexport const justifyCenter = () => execCommand('justifyCenter');\n\n/**\n * Right-aligns the current block.\n */\nexport const justifyRight = () => execCommand('justifyRight');\n\n/**\n * Fully justifies the current block.\n */\nexport const justifyFull = () => execCommand('justifyFull');\n\n/**\n * Indents the list or block.\n */\nexport const indent = () => execCommand('indent');\n\n/**\n * Outdents the list or block.\n * G.5: When cursor is inside a checklist item, \"outdent\" means converting\n * that item back to a regular <p> element rather than calling execCommand\n * (which would destroy the ul > li checklist structure).\n */\nexport function outdent() {\n const sel = window.getSelection();\n if (sel && sel.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const checkLi = container && container.closest && container.closest('.an-checklist li');\n if (checkLi) {\n _checklistItemToP(checkLi);\n return;\n }\n }\n execCommand('outdent');\n}\n\n/**\n * G.5 helper: splits a checklist at checkLi, converts it to a <p>,\n * and keeps items before/after as separate checklists.\n * @param {HTMLElement} checkLi\n */\nfunction _checklistItemToP(checkLi) {\n const checkUl = checkLi.closest('.an-checklist');\n if (!checkUl) return;\n\n const allLis = Array.from(checkUl.children);\n const liIndex = allLis.indexOf(checkLi);\n const afterLis = allLis.slice(liIndex + 1);\n\n // Build <p> from the item's text (skip the checkbox INPUT)\n const p = document.createElement('p');\n const text = Array.from(checkLi.childNodes)\n .filter(n => !(n.nodeType === 1 && n.tagName === 'INPUT'))\n .map(n => n.textContent).join('').replace(/\\u200B/g, '').trim();\n p.textContent = text || '\\u00a0';\n\n // Move items after the current li into a new checklist\n if (afterLis.length > 0) {\n const newUl = document.createElement('ul');\n newUl.className = 'an-checklist';\n afterLis.forEach(li => newUl.appendChild(li));\n checkUl.parentNode.insertBefore(newUl, checkUl.nextSibling);\n }\n\n // Insert <p> after checkUl (before any newUl)\n checkUl.parentNode.insertBefore(p, checkUl.nextSibling);\n\n // Remove current li from checkUl; delete checkUl if now empty\n checkUl.removeChild(checkLi);\n if (checkUl.children.length === 0) checkUl.parentNode.removeChild(checkUl);\n\n // Place caret at start of the new <p>\n try {\n const nr = document.createRange();\n const firstChild = p.firstChild;\n nr.setStart(firstChild && firstChild.nodeType === 3 ? firstChild : p, 0);\n nr.collapse(true);\n const s = window.getSelection();\n if (s) { s.removeAllRanges(); s.addRange(nr); }\n } catch {}\n}\n\n/**\n * Inserts an unordered list or converts selection.\n */\nexport const insertUnorderedList = () => execCommand('insertUnorderedList');\n\n/**\n * Inserts an ordered list or converts selection.\n */\nexport const insertOrderedList = () => execCommand('insertOrderedList');\n\n// ---------------------------------------------------------------------------\n// Line-height helper\n// ---------------------------------------------------------------------------\n\n/**\n * Applies a line-height value to every block-level element that intersects\n * the current selection.\n * @param {string} value - unitless multiplier, e.g. '1.5'\n */\nexport function lineHeight(value) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n\n const range = sel.getRangeAt(0);\n const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE', 'PRE', 'TD', 'TH']);\n\n const nearestBlock = (node) => {\n let el = node instanceof Element ? node : node.parentElement;\n while (el) {\n if (BLOCK_TAGS.has(el.tagName)) return el;\n el = el.parentElement;\n }\n return null;\n };\n\n if (range.collapsed) {\n const block = nearestBlock(range.startContainer);\n if (block) block.style.lineHeight = value;\n return;\n }\n\n // For a range selection, collect all unique block ancestors of text nodes\n const blocks = new Set();\n const iter = document.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_TEXT, null);\n let textNode;\n while ((textNode = iter.nextNode())) {\n if (range.intersectsNode(textNode)) {\n const block = nearestBlock(textNode);\n if (block) blocks.add(block);\n }\n }\n if (blocks.size === 0) {\n const block = nearestBlock(range.commonAncestorContainer);\n if (block) blocks.add(block);\n }\n blocks.forEach((block) => { block.style.lineHeight = value; });\n}\n\n// ---------------------------------------------------------------------------\n// Style query helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the computed styles relevant to the current cursor position.\n * @param {HTMLElement} editable\n * @returns {object} styleMap\n */\nexport function currentStyle(editable) {\n const range = currentRange(editable);\n if (!range) return {};\n\n const container = range.isCollapsed()\n ? range.sc\n : range.commonAncestor();\n\n const el = isElement(container) ? container : container.parentElement;\n if (!el) return {};\n\n const computed = window.getComputedStyle(el);\n\n return {\n bold: document.queryCommandState('bold'),\n italic: document.queryCommandState('italic'),\n underline: document.queryCommandState('underline'),\n strikethrough: document.queryCommandState('strikeThrough'),\n superscript: document.queryCommandState('superscript'),\n subscript: document.queryCommandState('subscript'),\n fontSize: computed.fontSize,\n fontFamily: computed.fontFamily,\n color: computed.color,\n backgroundColor: computed.backgroundColor,\n textAlign: computed.textAlign,\n lineHeight: computed.lineHeight,\n formatBlock: (closest(el, isPara, editable) || { nodeName: 'p' }).nodeName.toLowerCase(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Inline code toggle\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps the selection in an inline <code> element, or unwraps it if the\n * cursor is already inside a <code> that is not inside a <pre>.\n * @param {HTMLElement} [editable]\n */\nexport function toggleInlineCode(editable) {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n let container = range.commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const codeEl = container && container.closest ? container.closest('code') : null;\n if (codeEl && !codeEl.closest('pre')) {\n // Unwrap — save range endpoints relative to surrounding text so we can\n // restore the selection after normalize() merges adjacent text nodes.\n const parent = codeEl.parentNode;\n // Note the sibling before the code element so we can re-anchor later.\n const prevSibling = codeEl.previousSibling;\n const movedChildren = Array.from(codeEl.childNodes);\n while (codeEl.firstChild) parent.insertBefore(codeEl.firstChild, codeEl);\n parent.removeChild(codeEl);\n // Normalize only the immediate parent to merge adjacent text nodes without\n // invalidating distant selection anchors (full editable.normalize() can\n // cause selection offsets to shift, making subsequent format toggles miss).\n if (parent && parent.normalize) parent.normalize();\n // Restore selection to the text that was inside the unwrapped <code>.\n if (movedChildren.length > 0) {\n try {\n // After normalize, find the merged text node that contains the content.\n const firstMoved = movedChildren[0];\n const lastMoved = movedChildren[movedChildren.length - 1];\n const nr = document.createRange();\n // Use the (possibly merged) live node if still in the DOM.\n const anchorNode = (firstMoved.parentNode === parent) ? firstMoved : (prevSibling ? prevSibling.nextSibling : parent.firstChild);\n if (anchorNode) {\n nr.setStart(anchorNode, 0);\n const endAnchor = (lastMoved.parentNode === parent) ? lastMoved : anchorNode;\n nr.setEnd(endAnchor, endAnchor.nodeType === Node.TEXT_NODE ? endAnchor.textContent.length : endAnchor.childNodes.length);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n } catch (_) { /* ignore */ }\n }\n } else {\n if (range.collapsed) return;\n try {\n const code = document.createElement('code');\n range.surroundContents(code);\n // Re-select wrapped content so subsequent format toggles work\n const newRange = document.createRange();\n newRange.selectNodeContents(code);\n sel.removeAllRanges();\n sel.addRange(newRange);\n } catch {\n // surroundContents fails across element boundaries — extract and rewrap\n const frag = range.extractContents();\n const code = document.createElement('code');\n code.appendChild(frag);\n range.insertNode(code);\n // Re-select wrapped content\n const newRange = document.createRange();\n newRange.selectNodeContents(code);\n sel.removeAllRanges();\n sel.addRange(newRange);\n }\n }\n}\n\n/**\n * Returns true when the cursor / selection is inside an inline <code>\n * (not nested in a <pre>).\n * Uses startContainer for reliable cross-browser detection regardless of\n * whether the selection is collapsed or a range (commonAncestorContainer\n * can behave inconsistently for range selections on some browsers).\n * @returns {boolean}\n */\nexport function isInlineCode() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n const code = sc && sc.closest ? sc.closest('code') : null;\n return !!(code && !code.closest('pre'));\n}\n\n// ---------------------------------------------------------------------------\n// Checklist (task list)\n// ---------------------------------------------------------------------------\n\n/**\n * Toggles a task-list at the cursor.\n * If inside a checklist <li>, converts it (and any other selected items) back to <p> elements.\n * Otherwise inserts a new <ul class=\"an-checklist\"> with one item per selected line.\n */\nexport function toggleChecklist() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n let container = range.commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n\n const ul = container.closest && container.closest('.an-checklist');\n if (ul) {\n // If selection covers multiple <li>, convert them all\n const selectedLis = Array.from(ul.querySelectorAll('li')).filter((li) =>\n sel.containsNode(li, true),\n );\n if (selectedLis.length > 0) {\n let firstP = null;\n selectedLis.forEach((li) => {\n const text = Array.from(li.childNodes)\n .filter((n) => !(n.nodeType === 1 && n.tagName === 'INPUT'))\n .map((n) => n.textContent)\n .join('')\n .replace(/\\u00a0/g, ' ')\n .trim();\n const p = document.createElement('p');\n p.textContent = text || '\\u00a0';\n ul.parentNode.insertBefore(p, ul);\n if (!firstP) firstP = p;\n ul.removeChild(li);\n });\n if (ul.children.length === 0) ul.remove();\n // Move caret to first converted paragraph\n if (firstP) {\n const nr = document.createRange();\n nr.setStart(firstP.firstChild || firstP, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n return;\n }\n }\n\n // Otherwise: insert new checklist from selected text (or current block when collapsed).\n const isCollapsed = range.collapsed;\n if (isCollapsed) {\n // Find the nearest block-level ancestor (p, div, li, h1-h6, blockquote, etc.)\n // and convert it into a single checklist item.\n const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI']);\n let block = container;\n while (block && block.parentNode && !BLOCK_TAGS.has(block.tagName)) {\n block = block.parentNode;\n }\n // Fallback: if no block element found (e.g. cursor directly in editable root), use the\n // insertion approach with a zero-width-space item so the cursor ends up inside.\n const itemText = (block && BLOCK_TAGS.has(block.tagName))\n ? Array.from(block.childNodes)\n .map((n) => n.textContent)\n .join('')\n .replace(/\\u00a0/g, ' ')\n : '';\n\n const ul = document.createElement('ul');\n ul.className = 'an-checklist';\n const li = document.createElement('li');\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.contentEditable = 'false';\n li.appendChild(checkbox);\n li.appendChild(document.createTextNode(itemText || '\\u200B'));\n ul.appendChild(li);\n\n if (block && BLOCK_TAGS.has(block.tagName)) {\n block.parentNode.replaceChild(ul, block);\n } else {\n document.execCommand('insertHTML', false, ul.outerHTML);\n return;\n }\n\n // Move caret to the text node inside the new <li>\n const textNode = li.lastChild;\n const nr = document.createRange();\n const offset = textNode.nodeType === Node.TEXT_NODE ? textNode.textContent.length : 0;\n nr.setStart(textNode, offset);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return;\n }\n\n // G-4: Non-collapsed, non-checklist selection — convert each intersected\n // block element into a checklist item using direct DOM manipulation.\n // execCommand('insertHTML') is avoided here because in modern browsers it\n // deletes the selection but may silently fail to insert when the selection\n // spans multiple block elements, causing text to disappear.\n\n // Guard: if the raw selection is entirely whitespace, do nothing (mirrors\n // the old line-filter behaviour that prevented empty checklist creation).\n const rawSelText = sel.toString().replace(/[\\u00a0\\u200B]/g, ' ').trim();\n if (!rawSelText) return;\n\n const BLOCK_TAGS_MULTI = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'PRE', 'LI']);\n\n // Collect block-level ancestors of every node in the selection, in order.\n const blocks = [];\n const seenBlocks = new Set();\n const commonAncestor = range.commonAncestorContainer;\n const iter = document.createNodeIterator(\n commonAncestor.nodeType === Node.TEXT_NODE ? commonAncestor.parentNode : commonAncestor,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,\n null,\n );\n let node;\n while ((node = iter.nextNode())) {\n if (!range.intersectsNode(node)) continue;\n let block = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;\n while (block && !BLOCK_TAGS_MULTI.has(block.tagName)) {\n block = block.parentElement;\n }\n if (block && !seenBlocks.has(block)) {\n seenBlocks.add(block);\n blocks.push(block);\n }\n }\n\n if (blocks.length === 0) return;\n\n // Build checklist and replace collected blocks.\n const newUl = document.createElement('ul');\n newUl.className = 'an-checklist';\n let lastTextNode = null;\n blocks.forEach((block) => {\n const li = document.createElement('li');\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.setAttribute('contenteditable', 'false');\n li.appendChild(cb);\n // Preserve plain text content; ZWS/NBSP are stripped for display.\n const blockText = Array.from(block.childNodes)\n .map((n) => n.textContent)\n .join('')\n .replace(/[\\u00a0\\u200B]/g, ' ')\n .trim();\n const tn = document.createTextNode(blockText || '\\u200B');\n li.appendChild(tn);\n newUl.appendChild(li);\n lastTextNode = tn;\n });\n\n // Insert the new list before the first block, then remove all source blocks.\n const firstBlock = blocks[0];\n firstBlock.parentNode.insertBefore(newUl, firstBlock);\n blocks.forEach((block) => block.parentNode && block.parentNode.removeChild(block));\n\n // Move caret to end of the last checklist item.\n if (lastTextNode) {\n const nr = document.createRange();\n nr.setStart(lastTextNode, lastTextNode.textContent.length);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n}\n\n/**\n * Returns true when the cursor is inside a checklist item.\n * @returns {boolean}\n */\nexport function isInChecklist() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n return !!(container && container.closest && container.closest('.an-checklist li'));\n}\n","/**\n * Buttons.js - Toolbar button definitions and factories\n * All buttons are plain objects describing their appearance and action.\n * They are rendered by the Toolbar module.\n */\n\nimport * as Style from '../editing/Style.js';\n\n// ---------------------------------------------------------------------------\n// Dropdown definition helper\n// ---------------------------------------------------------------------------\n\n/**\n * @typedef {object} DropdownDef\n * @property {string} name - unique identifier\n * @property {'select'} type - discriminator for Toolbar renderer\n * @property {string} tooltip\n * @property {string[]} [items] - overridden at render time from options\n * @property {Function} action - called with (context, value)\n * @property {Function} [getValue] - called with (context) to get current value\n */\n\n// ---------------------------------------------------------------------------\n// Button factory helpers\n// ---------------------------------------------------------------------------\n\n/**\n * @typedef {object} ButtonDef\n * @property {string} name - unique identifier\n * @property {string} icon - SVG or HTML icon markup / text\n * @property {string} tooltip - tooltip string\n * @property {Function} action - called with (context) when clicked\n * @property {Function} [isActive] - called with (context) to determine active state\n * @property {Function} [isDisabled] - called with (context) to determine disabled state\n * @property {string} [className] - extra CSS class(es)\n */\n\n/**\n * Creates a simple button definition.\n * @param {string} name\n * @param {string} icon\n * @param {string} tooltip\n * @param {Function} action\n * @param {Function} [isActive]\n * @param {Function} [isDisabled]\n * @returns {ButtonDef}\n */\nfunction btn(name, icon, tooltip, action, isActive, isDisabled) {\n // `icon` is an identifier (e.g. 'bold', 'italic'). Rendering to\n // visual markup (FontAwesome or fallback) is done in Toolbar._createButton\n return { name, icon, tooltip, action, isActive, isDisabled };\n}\n\n// ---------------------------------------------------------------------------\n// Style buttons\n// ---------------------------------------------------------------------------\n\nexport const boldBtn = btn('bold', 'bold', 'Bold (Ctrl+B)', () => Style.bold(), () => document.queryCommandState('bold'));\nexport const italicBtn = btn('italic', 'italic', 'Italic (Ctrl+I)', () => Style.italic(), () => document.queryCommandState('italic'));\nexport const underlineBtn = btn('underline', 'underline', 'Underline (Ctrl+U)', () => Style.underline(), () => {\n // queryCommandState('underline') is unreliable inside <code> elements;\n // also check for a <u> ancestor in the DOM using startContainer for\n // consistent behaviour across both collapsed and range selections.\n if (document.queryCommandState('underline')) return true;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n return !!(sc && sc.closest && sc.closest('u'));\n});\nexport const strikeBtn = btn('strikethrough', 'strikethrough', 'Strikethrough', () => Style.strikethrough(), () => document.queryCommandState('strikeThrough'));\nexport const superscriptBtn = btn('superscript', 'superscript', 'Superscript', () => Style.superscript(), () => document.queryCommandState('superscript'));\nexport const subscriptBtn = btn('subscript', 'subscript', 'Subscript', () => Style.subscript(), () => document.queryCommandState('subscript'));\n\n// ---------------------------------------------------------------------------\n// Alignment buttons\n// ---------------------------------------------------------------------------\n\nexport const alignLeftBtn = btn('alignLeft', 'align-left', 'Align Left', () => Style.justifyLeft());\nexport const alignCenterBtn = btn('alignCenter', 'align-center', 'Align Center', () => Style.justifyCenter());\nexport const alignRightBtn = btn('alignRight', 'align-right', 'Align Right', () => Style.justifyRight());\nexport const alignJustifyBtn = btn('alignJustify', 'align-justify', 'Justify', () => Style.justifyFull());\n\n// ---------------------------------------------------------------------------\n// List buttons\n// ---------------------------------------------------------------------------\n\nexport const ulBtn = btn('ul', 'list-ul', 'Unordered List', () => Style.insertUnorderedList());\nexport const olBtn = btn('ol', 'list-ol', 'Ordered List', () => Style.insertOrderedList());\n\n// ---------------------------------------------------------------------------\n// Indent buttons\n// ---------------------------------------------------------------------------\n\nexport const indentBtn = btn('indent', 'indent', 'Indent', () => Style.indent());\nexport const outdentBtn = btn('outdent', 'outdent', 'Outdent', () => Style.outdent());\n\n// ---------------------------------------------------------------------------\n// Undo / redo buttons\n// ---------------------------------------------------------------------------\n\nexport const undoBtn = btn('undo', 'undo', 'Undo (Ctrl+Z)', (_ctx) => _ctx.invoke('editor.undo'), undefined, (ctx) => !ctx.invoke('editor.canUndo'));\nexport const redoBtn = btn('redo', 'redo', 'Redo (Ctrl+Y)', (_ctx) => _ctx.invoke('editor.redo'), undefined, (ctx) => !ctx.invoke('editor.canRedo'));\n\n// ---------------------------------------------------------------------------\n// Insert media — HR, Link, Image\n// ---------------------------------------------------------------------------\n\nexport const hrBtn = btn('hr', 'minus', 'Horizontal Rule', () => Style.execCommand('insertHorizontalRule'));\nexport const linkBtn = btn('link', 'link', 'Insert Link', (ctx) => ctx.invoke('linkDialog.show'));\nexport const imageBtn = btn('image', 'image', 'Insert Image', (ctx) => ctx.invoke('imageDialog.show'));\nexport const videoBtn = btn('video', 'video', 'Insert Video', (ctx) => ctx.invoke('videoDialog.show'));\nexport const emojiBtn = btn('emoji', 'emoji', 'Insert Emoji', (ctx) => ctx.invoke('emojiDialog.show'));\nexport const iconBtn = btn('icon', 'icon', 'Insert FA Icon', (ctx) => ctx.invoke('iconDialog.show'));\n\n/** @type {ButtonDef & { type: 'grid' }} */\nexport const tableBtn = {\n name: 'table',\n type: 'grid',\n icon: 'table',\n tooltip: 'Insert Table',\n action: (ctx, rows, cols) => {\n ctx.invoke('editor.insertTable', cols, rows);\n ctx.invoke('editor.afterCommand');\n },\n};\n\n// ---------------------------------------------------------------------------\n// Font size dropdown\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const fontSizeBtn = {\n name: 'fontSize',\n type: 'select',\n tooltip: 'Font Size',\n placeholder: 'Size',\n selectClass: 'an-select-narrow',\n items: ['8px', '10px', '11px', '12px', '13px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px', '72px'],\n action: (ctx, value) => Style.fontSize(value, ctx.layoutInfo.editable),\n getValue: (ctx) => {\n try {\n const sel = window.getSelection();\n if (sel && sel.rangeCount) {\n let el = sel.getRangeAt(0).startContainer;\n if (el.nodeType === 3) el = el.parentElement;\n while (el && el.nodeType === 1 && !el.style.fontSize) el = el.parentElement;\n const size = (el && el.style && el.style.fontSize) ? el.style.fontSize : '';\n if (size) return size;\n }\n // Fallback: read the base font size from the editable element itself\n const editable = ctx && ctx.layoutInfo && ctx.layoutInfo.editable;\n if (editable) return editable.style.fontSize || '';\n return '';\n } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Remove format button\n// ---------------------------------------------------------------------------\n\nexport const removeFormatBtn = btn('removeFormat', 'remove-format', 'Remove Format', () => Style.execCommand('removeFormat'));\n\n// ---------------------------------------------------------------------------\n// Direction (LTR / RTL) toggle button\n// ---------------------------------------------------------------------------\n\nexport const directionBtn = btn(\n 'direction',\n 'direction',\n 'Toggle Text Direction (LTR / RTL)',\n (ctx) => {\n const editable = ctx.layoutInfo.editable;\n const current = editable.getAttribute('dir') || 'ltr';\n const next = current === 'ltr' ? 'rtl' : 'ltr';\n editable.setAttribute('dir', next);\n editable.style.textAlign = next === 'rtl' ? 'right' : 'left';\n ctx.invoke('editor.afterCommand');\n },\n);\n\n// ---------------------------------------------------------------------------\n// Font family dropdown\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const fontFamilyBtn = {\n name: 'fontFamily',\n type: 'select',\n tooltip: 'Font Family',\n action: (ctx, value) => Style.fontName(value),\n getValue: () => {\n try { return document.queryCommandValue('fontName') || ''; } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Paragraph style dropdown (Normal / H1-H6 / Quote / Code)\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const paragraphStyleBtn = {\n name: 'paragraphStyle',\n type: 'select',\n tooltip: 'Paragraph Style',\n placeholder: 'Style',\n selectClass: 'an-select-style',\n items: [\n { value: 'p', label: 'Normal' },\n { value: 'h1', label: 'H1' },\n { value: 'h2', label: 'H2' },\n { value: 'h3', label: 'H3' },\n { value: 'h4', label: 'H4' },\n { value: 'h5', label: 'H5' },\n { value: 'h6', label: 'H6' },\n { value: 'blockquote', label: 'Quote' },\n { value: 'pre', label: 'Code' },\n ],\n action: (_ctx, value) => Style.formatBlock(value),\n getValue: () => {\n try {\n const raw = document.queryCommandValue('formatBlock').toLowerCase().replace(/[<>]/g, '');\n return raw === 'div' ? 'p' : (raw || 'p');\n } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Line-height dropdown\n// ---------------------------------------------------------------------------\n\n/** @type {DropdownDef} */\nexport const lineHeightBtn = {\n name: 'lineHeight',\n type: 'select',\n tooltip: 'Line Height',\n placeholder: '\\u2195 Line',\n selectClass: 'an-select-narrow',\n items: ['1.0', '1.15', '1.5', '1.75', '2.0', '2.5', '3.0'],\n action: (_ctx, value) => Style.lineHeight(value),\n getValue: () => {\n try {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return '';\n const BLOCKS = new Set(['P','DIV','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE','PRE','TD','TH']);\n let el = sel.getRangeAt(0).startContainer;\n if (el.nodeType === 3) el = el.parentElement;\n while (el && !BLOCKS.has(el.tagName)) el = el.parentElement;\n if (!el) return '';\n return el.style.lineHeight || getComputedStyle(el).lineHeight || '';\n } catch { return ''; }\n },\n};\n\n// ---------------------------------------------------------------------------\n// Code view / fullscreen\n// ---------------------------------------------------------------------------\n\nexport const codeviewBtn = btn('codeview', 'code', 'HTML Code View', (ctx) => ctx.invoke('codeview.toggle'), (ctx) => ctx.invoke('codeview.isActive'));\nexport const fullscreenBtn = btn('fullscreen', 'expand', 'Fullscreen', (ctx) => ctx.invoke('fullscreen.toggle'), (ctx) => ctx.invoke('fullscreen.isActive'));\nexport const shortcutsBtn = btn('shortcuts', 'keyboard', 'Keyboard Shortcuts (Ctrl+Shift+/)', (ctx) => ctx.invoke('shortcutsDialog.show'));\nexport const findBtn = btn('find', 'search', 'Find (Ctrl+F)', (ctx) => ctx.invoke('findReplace.show', 'find'));\nexport const findReplaceBtn = btn('findReplace', 'find-replace', 'Find & Replace (Ctrl+H)', (ctx) => ctx.invoke('findReplace.show', 'replace'));\nexport const inlineCodeBtn = btn('inlineCode', 'inline-code', 'Inline Code (Ctrl+`)', (ctx) => ctx.invoke('editor.inlineCode'), () => Style.isInlineCode());\nexport const checklistBtn = btn('checklist', 'checklist', 'Checklist', (ctx) => ctx.invoke('editor.toggleChecklist'), () => Style.isInChecklist());\nexport const printBtn = btn('print', 'print', 'Print', (ctx) => ctx.invoke('editor.print'));\n\n// ---------------------------------------------------------------------------\n// Text / background colour pickers\n// ---------------------------------------------------------------------------\n\n/** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */\nexport const foreColorBtn = {\n name: 'foreColor',\n type: 'colorpicker',\n icon: 'foreColor',\n tooltip: 'Text Color',\n defaultColor: '#e11d48',\n action: (ctx, color) => Style.foreColor(color),\n};\n\n/** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */\nexport const backColorBtn = {\n name: 'backColor',\n type: 'colorpicker',\n icon: 'backColor',\n tooltip: 'Highlight Color',\n defaultColor: '#fbbf24',\n action: (ctx, color) => Style.backColor(color),\n};\n\n// ---------------------------------------------------------------------------\n// Default toolbar layout\n// ---------------------------------------------------------------------------\n\n/**\n * The default toolbar button groups.\n * Each sub-array is a button group (separated by a divider).\n */\nexport const defaultToolbar = [\n [paragraphStyleBtn, fontFamilyBtn, fontSizeBtn, lineHeightBtn],\n [undoBtn, redoBtn],\n [boldBtn, italicBtn, underlineBtn, strikeBtn, inlineCodeBtn],\n [superscriptBtn, subscriptBtn],\n [foreColorBtn, backColorBtn],\n [alignLeftBtn, alignCenterBtn, alignRightBtn, alignJustifyBtn],\n [ulBtn, olBtn, checklistBtn, indentBtn, outdentBtn],\n [hrBtn, linkBtn, imageBtn, videoBtn, tableBtn, emojiBtn, iconBtn],\n [removeFormatBtn, codeviewBtn, fullscreenBtn, findBtn, printBtn, shortcutsBtn],\n];\n","/**\n * settings.js - Default editor options\n * Inspired by Summernote's settings.js\n */\n\nimport { defaultToolbar } from './module/Buttons.js';\n\n/**\n * @typedef {object} AsnOptions\n * @property {string} [placeholder] - Placeholder text when editor is empty\n * @property {number} [height] - Editor height in px (min)\n * @property {number} [minHeight] - Minimum height in px\n * @property {number} [maxHeight] - Maximum height in px (0 = unlimited)\n * @property {boolean} [focus] - Auto-focus on init\n * @property {boolean} [resizable] - Show resize handle\n * @property {Array} [toolbar] - Toolbar button group config\n * @property {boolean} [pasteAsPlainText] - Force plain-text paste\n * @property {boolean} [pasteCleanHTML] - Sanitise HTML on paste\n * @property {boolean} [pasteStripAttributes] - Strip class/style/data-* from pasted HTML (default: false)\n * @property {boolean} [allowImageUpload] - Allow file upload in image dialog\n * @property {number} [maxImageSize] - Max upload size in MB\n * @property {number} [tabSize] - Spaces per tab in non-list context\n * @property {Function} [onChange] - Callback on content change\n * @property {Function} [onFocus] - Callback on focus\n * @property {Function} [onBlur] - Callback on blur\n * @property {Function} [onImageUpload] - Custom upload handler: (files) => void\n * @property {boolean} [stickyToolbar] - Stick the toolbar to the viewport top when scrolling\n * @property {number} [stickyToolbarOffset] - Top offset in px for sticky toolbar (e.g. fixed nav height)\n * @property {string} [theme] - 'light' (default) | 'dark'\n * @property {boolean} [codeHighlight] - Auto-load Prism.js for syntax highlighting of code blocks\n * @property {string} [codeHighlightCDN] - CDN base URL for Prism assets (defaults to cdnjs)\n * @property {boolean} [markdownPaste] - Convert pasted Markdown text to HTML (default: true)\n * @property {boolean} [readOnly] - Start editor in read-only / non-editable mode\n * @property {boolean} [spellcheck] - Enable browser spellcheck in the editable area (default: true)\n * @property {string} [direction] - Text direction: 'ltr' (default) | 'rtl'\n * @property {string} [toolbarOverflow] - Toolbar overflow strategy: 'wrap' (default) | 'scroll'\n * @property {boolean} [autoSave] - Auto-save content to localStorage on change\n * @property {string} [autoSaveKey] - localStorage key used for auto-save (default: 'autumnnote-autosave')\n * @property {number} [maxChars] - Maximum character count (0 = unlimited). Shows warning in statusbar.\n * @property {number} [maxWords] - Maximum word count (0 = unlimited). Shows warning in statusbar.\n * @property {boolean} [tableHeaderRow] - Insert a header row (<thead><th>) when creating tables\n * @property {Function} [onPaste] - Callback fired on every paste: ({ text, html }) => void\n * @property {Function} [onSelectionChange] - Callback fired on cursor/selection change: (context) => void\n * @property {string[]} [colorSwatches] - Custom brand colour swatches prepended to the colour-picker palette\n * @property {Function} [onDestroy] - Callback fired when the editor is destroyed: (context) => void\n * @property {Function} [onCharLimitReached] - Callback fired when the character limit is hit: (context) => void\n * @property {Function} [onWordLimitReached] - Callback fired when the word limit is hit: (context) => void\n * @property {string} [focusColor] - Custom focus ring colour, e.g. '#f97316'. Overrides the default blue.\n */\n\n/** @type {AsnOptions} */\nexport const defaultOptions = {\n placeholder: '',\n height: 200,\n minHeight: 100,\n maxHeight: 0,\n focus: false,\n resizable: true,\n toolbar: defaultToolbar,\n // UI integration options\n // If `useBootstrap` is true, toolbar buttons will use the Bootstrap button classes\n // (set `toolbarButtonClass` to customize). Works with Bootstrap 4 and 5.\n useBootstrap: false,\n toolbarButtonClass: 'btn btn-sm btn-light',\n // Icon options — uses Font Awesome by default. Consumers must include Font Awesome CSS.\n useFontAwesome: true,\n // Default FontAwesome prefix — 'fas' for FA5, 'fa-solid' for FA6. Change if needed.\n fontAwesomeClass: 'fas',\n pasteAsPlainText: false,\n pasteCleanHTML: true,\n pasteStripAttributes: false,\n allowImageUpload: true,\n maxImageSize: 5,\n tabSize: 4,\n onChange: null,\n onFocus: null,\n onBlur: null,\n onInit: null,\n onImageUpload: null,\n onImageError: null,\n stickyToolbar: false,\n stickyToolbarOffset: 0,\n theme: 'light',\n codeHighlight: true,\n codeHighlightCDN: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0',\n markdownPaste: true,\n historyLimit: 100,\n // Default font family applied to the editor and shown in the dropdown when no explicit font is set\n defaultFontFamily: 'Arial',\n // Default font size applied to the editor and shown in the size dropdown when no explicit size is set\n defaultFontSize: '14px',\n // Font families shown in the toolbar font-family dropdown\n fontFamilies: [\n 'Arial',\n 'Arial Black',\n 'Comic Sans MS',\n 'Courier New',\n 'Georgia',\n 'Impact',\n 'Tahoma',\n 'Times New Roman',\n 'Trebuchet MS',\n 'Verdana',\n ],\n // Read-only mode — disables all editing when true\n readOnly: false,\n // Enable/disable browser spell-check on the editable area\n spellcheck: true,\n // Text direction: 'ltr' (default) or 'rtl'\n direction: 'ltr',\n // How the toolbar handles overflow: 'wrap' (default, wraps to next line) or 'scroll' (single scrollable row)\n toolbarOverflow: 'wrap',\n // Auto-save content to localStorage on every change\n autoSave: false,\n // localStorage key used when autoSave is enabled\n autoSaveKey: 'autumnnote-autosave',\n // Maximum character count (0 = unlimited)\n maxChars: 0,\n // Maximum word count (0 = unlimited)\n maxWords: 0,\n // Insert a header row (<thead>) when creating new tables\n tableHeaderRow: false,\n // Callback fired on every cursor/selection change inside the editor\n onSelectionChange: null,\n // Custom brand colour swatches to prepend to the toolbar colour-picker palette\n colorSwatches: [],\n // Callback fired after a paste event: function({ text, html })\n onPaste: null,\n // Callback fired just before the editor instance is destroyed\n onDestroy: null,\n // Callback fired when the character limit is reached: function(context)\n onCharLimitReached: null,\n // Callback fired when the word limit is reached: function(context)\n onWordLimitReached: null,\n // Custom focus ring colour — overrides the default blue when set.\n // Accepts any valid CSS colour string, e.g. '#f97316', 'hsl(25,90%,55%)'.\n focusColor: null,\n // Display language for the editor UI.\n // Built-in values: 'en' (default), 'vi', 'ja', 'zh', 'fr'.\n // Pass a partial or full locale object to override individual strings.\n lang: 'en',\n\n // Auto-save restore: show a banner when a draft exists in localStorage.\n // Requires autoSave: true. Set autoSaveRestoreTimeout to the max age in days\n // (0 = no expiry). onAutoSaveRestore(html, context) fires after restore.\n autoSaveRestore: false,\n autoSaveRestoreTimeout: 7,\n onAutoSaveRestore: null,\n\n // Markdown input shortcuts: convert markdown syntax typed inline to HTML.\n // e.g. \"## \" at line start → <h2>, \"**bold**\" → <strong>\n markdownShortcuts: true,\n\n // Bubble toolbar: show a mini floating toolbar above text selections.\n bubbleToolbar: false,\n bubbleToolbarItems: ['bold', 'italic', 'underline', 'link', 'foreColor', 'removeFormat'],\n\n // @mention support. mention.onSearch(query, callback) must be provided to activate.\n // mention.minChars defaults to 0 — dropdown opens immediately on trigger character.\n mention: null,\n};\n","/**\n * en.js - English locale (canonical reference)\n * All other locales deep-merge against this to fill missing keys.\n */\n\n/** @type {import('../../../types/index.js').AsnLocale} */\nexport const en = {\n toolbar: {\n bold: 'Bold (Ctrl+B)',\n italic: 'Italic (Ctrl+I)',\n underline: 'Underline (Ctrl+U)',\n strikethrough: 'Strikethrough',\n superscript: 'Superscript',\n subscript: 'Subscript',\n alignLeft: 'Align Left',\n alignCenter: 'Align Center',\n alignRight: 'Align Right',\n alignJustify: 'Justify',\n ul: 'Unordered List',\n ol: 'Ordered List',\n checklist: 'Checklist',\n indent: 'Indent',\n outdent: 'Outdent',\n undo: 'Undo (Ctrl+Z)',\n redo: 'Redo (Ctrl+Y)',\n hr: 'Horizontal Rule',\n link: 'Insert Link',\n image: 'Insert Image',\n video: 'Insert Video',\n emoji: 'Insert Emoji',\n icon: 'Insert FA Icon',\n table: 'Insert Table',\n fontSize: 'Font Size',\n fontSizePlaceholder: 'Size',\n removeFormat: 'Remove Format',\n direction: 'Toggle Text Direction (LTR / RTL)',\n fontFamily: 'Font Family',\n paragraphStyle: 'Paragraph Style',\n paragraphStylePlaceholder: 'Style',\n lineHeight: 'Line Height',\n lineHeightPlaceholder: '\\u2195 Line',\n codeview: 'HTML Code View',\n fullscreen: 'Fullscreen',\n shortcuts: 'Keyboard Shortcuts (Ctrl+Shift+/)',\n find: 'Find (Ctrl+F)',\n findReplace: 'Find & Replace (Ctrl+H)',\n inlineCode: 'Inline Code (Ctrl+`)',\n print: 'Print',\n foreColor: 'Text Color',\n backColor: 'Highlight Color',\n chooseTextColor: 'Choose text color',\n chooseHighlightColor: 'Choose highlight color',\n customColor: 'Custom color',\n insertTableLabel: 'Insert Table',\n /** Map of paragraph-style value → label (only values needing translation) */\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Quote',\n pre: 'Code',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Insert link',\n title: 'Insert Link',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Display Text',\n textPlaceholder: 'Link text',\n openInNewTab: 'Open in new tab',\n insertBtn: 'Insert',\n cancelBtn: 'Cancel',\n },\n\n imageDialog: {\n ariaLabel: 'Insert image',\n title: 'Insert Image',\n imageUrl: 'Image URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Alt Text',\n altPlaceholder: 'Describe the image',\n alignment: 'Alignment',\n alignNone: 'None',\n alignLeft: 'Left',\n alignCenter: 'Center',\n alignRight: 'Right',\n uploadLabel: 'Or upload a file',\n insertBtn: 'Insert',\n cancelBtn: 'Cancel',\n },\n\n videoDialog: {\n ariaLabel: 'Insert video',\n title: 'Insert Video',\n videoUrl: 'Video URL',\n urlPlaceholder: 'YouTube, Vimeo, or direct .mp4 URL',\n widthLabel: 'Width (px)',\n widthPlaceholder: '560',\n insertBtn: 'Insert',\n cancelBtn: 'Cancel',\n /** @param {string} type */\n detected: (type) => `Detected: ${type}`,\n unknownFormat: 'Unknown format \\u2014 will try direct video embed',\n invalidUrl: 'Invalid URL \\u2014 please enter a valid video link.',\n },\n\n emojiDialog: {\n ariaLabel: 'Insert emoji',\n title: 'Insert Emoji',\n searchPlaceholder: 'Search emojis\\u2026',\n all: 'All',\n cancelBtn: 'Cancel',\n close: 'Close',\n categories: {\n smileys: 'Smileys',\n people: 'People',\n animals: 'Animals',\n food: 'Food',\n travel: 'Travel',\n objects: 'Objects',\n symbols: 'Symbols',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Insert FA icon',\n title: 'Insert FA Icon',\n searchPlaceholder: 'Search icons\\u2026',\n all: 'All',\n style: 'Style',\n size: 'Size',\n color: 'Color',\n useColor: ' Use color',\n selectHint: 'Select an icon',\n insertBtn: 'Insert FA Icon',\n cancelBtn: 'Cancel',\n close: 'Close',\n categories: {\n popular: 'Popular',\n interface: 'Interface',\n navigation: 'Navigation',\n media: 'Media',\n communication: 'Communication',\n files: 'Files',\n people: 'People',\n objects: 'Objects',\n },\n },\n\n findReplace: {\n findTitle: 'Find',\n findReplaceTitle: 'Find & Replace',\n findPlaceholder: 'Find\\u2026',\n searchAriaLabel: 'Search text',\n caseSensitive: '\\u00a0Case sensitive',\n prevBtn: '\\u2190 Prev',\n nextBtn: 'Next \\u2192',\n replacePlaceholder: 'Replace with\\u2026',\n replaceAriaLabel: 'Replace with',\n replaceBtn: 'Replace',\n replaceAllBtn: 'Replace All',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'Keyboard Shortcuts',\n ariaLabel: 'Keyboard Shortcuts',\n close: 'Close',\n shortcuts: [\n {\n category: 'Text Formatting',\n items: [\n { keys: 'Ctrl + B', action: 'Bold' },\n { keys: 'Ctrl + I', action: 'Italic' },\n { keys: 'Ctrl + U', action: 'Underline' },\n { keys: 'Ctrl + K', action: 'Insert / edit link' },\n ],\n },\n {\n category: 'History',\n items: [\n { keys: 'Ctrl + Z', action: 'Undo' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Redo' },\n ],\n },\n {\n category: 'Selection & Navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Select all content' },\n { keys: 'Tab', action: 'Indent list item / insert spaces' },\n { keys: 'Shift + Tab', action: 'Outdent list item' },\n ],\n },\n {\n category: 'Clipboard',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Paste as plain text' },\n ],\n },\n {\n category: 'Find & Replace',\n items: [\n { keys: 'Ctrl + F', action: 'Find in document' },\n { keys: 'Ctrl + H', action: 'Find & Replace' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Show this keyboard shortcuts dialog' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Cut',\n copy: 'Copy',\n paste: 'Paste',\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n textColor: 'Text Color',\n highlightColor: 'Highlight Color',\n copyFormat: 'Copy Format',\n pasteFormat: 'Paste Format',\n removeFormat: 'Remove Format',\n link: 'Insert Link',\n image: 'Insert Image',\n video: 'Insert Video',\n table: 'Insert Table',\n back: 'Back',\n noHighlight: 'No highlight',\n customColor: 'Custom color',\n customColorLabel: 'Custom\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'Resize editor',\n /** @param {number} n */\n words: (n) => `Words: ${n}`,\n /** @param {number} n @param {number} max */\n wordsLimit: (n, max) => `Words: ${n}/${max}`,\n /** @param {number} n */\n chars: (n) => `Chars: ${n}`,\n /** @param {number} n @param {number} max */\n charsLimit: (n, max) => `Chars: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Link actions',\n openLink: 'Open link',\n copyUrl: 'Copy URL',\n editLink: 'Edit link',\n removeLink: 'Remove link',\n },\n image: {\n ariaLabel: 'Image actions',\n label: 'Image',\n floatLeft: 'Float Left',\n noFloat: 'No Float',\n alignCenter: 'Align Center',\n floatRight: 'Float Right',\n originalSize: 'Original Size',\n rotateLeft: 'Rotate Left',\n rotateRight: 'Rotate Right',\n cropImage: 'Crop Image',\n addCaption: 'Add / Edit Caption',\n deleteImage: 'Delete Image',\n },\n code: {\n ariaLabel: 'Code block actions',\n label: 'Code',\n syntaxLanguage: 'Syntax Language',\n syntaxAriaLabel: 'Syntax language',\n copyCode: 'Copy Code',\n toggleWordWrap: 'Toggle Word Wrap',\n enableWordWrap: 'Enable Word Wrap',\n disableWordWrap: 'Disable Word Wrap',\n convertToParagraph: 'Convert to Paragraph',\n deleteCodeBlock: 'Delete Code Block',\n },\n table: {\n ariaLabel: 'Table actions',\n label: 'Table',\n selectCells: 'Select Cells',\n addRowAbove: 'Add Row Above',\n addRowBelow: 'Add Row Below',\n deleteRow: 'Delete Row',\n addColumnLeft: 'Add Column Left',\n addColumnRight: 'Add Column Right',\n deleteColumn: 'Delete Column',\n mergeCells: 'Merge Cells',\n unmergeCells: 'Unmerge Cells',\n columnWidth: 'Column Width',\n rowHeight: 'Row Height',\n tableBorderWidth: 'Table Border Width',\n deleteTable: 'Delete Table',\n columnWidthPx: 'Column Width (px)',\n rowHeightPx: 'Row Height (px)',\n tableBorderWidthPx: 'Table Border Width (px)',\n cancelBtn: 'Cancel',\n applyBtn: 'Apply',\n },\n video: {\n ariaLabel: 'Video actions',\n label: 'Video',\n floatLeft: 'Float Left',\n noFloat: 'No Float',\n alignCenter: 'Align Center',\n floatRight: 'Float Right',\n originalSize: 'Original Size',\n previewVideo: 'Preview Video',\n exitPreview: 'Exit Preview',\n deleteVideo: 'Delete Video',\n },\n },\n\n errors: {\n /** @param {string} type */\n imageFormat: (type) =>\n `Format \"${type}\" is not supported for display in web browsers. Please convert to JPEG, PNG, or WebP first.`,\n /** @param {number} maxSize */\n imageSize: (maxSize) =>\n `Image file is too large. Maximum allowed size is ${maxSize} MB.`,\n },\n};\n","/**\n * vi.js - Tiếng Việt locale\n * Chỉ cần khai báo các key khác với tiếng Anh (en.js).\n * Các key còn lại sẽ được lấy từ en.js qua deep-merge.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const vi = {\n toolbar: {\n bold: 'Đậm (Ctrl+B)',\n italic: 'Nghiêng (Ctrl+I)',\n underline: 'Gạch chân (Ctrl+U)',\n strikethrough: 'Gạch ngang',\n superscript: 'Chỉ số trên',\n subscript: 'Chỉ số dưới',\n alignLeft: 'Căn trái',\n alignCenter: 'Căn giữa',\n alignRight: 'Căn phải',\n alignJustify: 'Căn đều',\n ul: 'Danh sách không thứ tự',\n ol: 'Danh sách có thứ tự',\n checklist: 'Danh sách kiểm tra',\n indent: 'Tăng thụt đầu dòng',\n outdent: 'Giảm thụt đầu dòng',\n undo: 'Hoàn tác (Ctrl+Z)',\n redo: 'Làm lại (Ctrl+Y)',\n hr: 'Đường kẻ ngang',\n link: 'Chèn liên kết',\n image: 'Chèn hình ảnh',\n video: 'Chèn video',\n emoji: 'Chèn biểu tượng cảm xúc',\n icon: 'Chèn biểu tượng FA',\n table: 'Chèn bảng',\n fontSize: 'Cỡ chữ',\n fontSizePlaceholder: 'Cỡ',\n removeFormat: 'Xóa định dạng',\n direction: 'Chuyển hướng văn bản (LTR / RTL)',\n fontFamily: 'Phông chữ',\n paragraphStyle: 'Kiểu đoạn văn',\n paragraphStylePlaceholder: 'Kiểu',\n lineHeight: 'Khoảng cách dòng',\n lineHeightPlaceholder: '\\u2195 Dòng',\n codeview: 'Xem mã HTML',\n fullscreen: 'Toàn màn hình',\n shortcuts: 'Phím tắt (Ctrl+Shift+/)',\n find: 'Tìm kiếm (Ctrl+F)',\n findReplace: 'Tìm & Thay thế (Ctrl+H)',\n inlineCode: 'Mã nội tuyến (Ctrl+`)',\n print: 'In',\n foreColor: 'Màu chữ',\n backColor: 'Màu nền chữ',\n chooseTextColor: 'Chọn màu chữ',\n chooseHighlightColor: 'Chọn màu nền',\n customColor: 'Màu tùy chỉnh',\n insertTableLabel: 'Chèn bảng',\n paragraphItems: {\n p: 'Bình thường',\n blockquote: 'Trích dẫn',\n pre: 'Mã',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Chèn liên kết',\n title: 'Chèn liên kết',\n url: 'Địa chỉ URL',\n urlPlaceholder: 'https://',\n displayText: 'Văn bản hiển thị',\n textPlaceholder: 'Nội dung liên kết',\n openInNewTab: 'Mở trong tab mới',\n insertBtn: 'Chèn',\n cancelBtn: 'Hủy',\n },\n\n imageDialog: {\n ariaLabel: 'Chèn hình ảnh',\n title: 'Chèn hình ảnh',\n imageUrl: 'URL hình ảnh',\n urlPlaceholder: 'https://example.com/anh.png',\n altText: 'Văn bản thay thế',\n altPlaceholder: 'Mô tả hình ảnh',\n alignment: 'Căn chỉnh',\n alignNone: 'Không',\n alignLeft: 'Trái',\n alignCenter: 'Giữa',\n alignRight: 'Phải',\n uploadLabel: 'Hoặc tải lên tệp',\n insertBtn: 'Chèn',\n cancelBtn: 'Hủy',\n },\n\n videoDialog: {\n ariaLabel: 'Chèn video',\n title: 'Chèn video',\n videoUrl: 'URL video',\n urlPlaceholder: 'YouTube, Vimeo, hoặc URL .mp4 trực tiếp',\n widthLabel: 'Chiều rộng (px)',\n widthPlaceholder: '560',\n insertBtn: 'Chèn',\n cancelBtn: 'Hủy',\n detected: (type) => `Đã phát hiện: ${type}`,\n unknownFormat: 'Định dạng không xác định \\u2014 sẽ thử nhúng video trực tiếp',\n invalidUrl: 'URL không hợp lệ \\u2014 vui lòng nhập đường dẫn video hợp lệ.',\n },\n\n emojiDialog: {\n ariaLabel: 'Chèn biểu tượng cảm xúc',\n title: 'Chèn biểu tượng cảm xúc',\n searchPlaceholder: 'Tìm kiếm biểu tượng\\u2026',\n all: 'Tất cả',\n cancelBtn: 'Hủy',\n close: 'Đóng',\n categories: {\n smileys: 'Mặt cười',\n people: 'Con người',\n animals: 'Động vật',\n food: 'Thức ăn',\n travel: 'Du lịch',\n objects: 'Đồ vật',\n symbols: 'Ký hiệu',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Chèn biểu tượng FA',\n title: 'Chèn biểu tượng FA',\n searchPlaceholder: 'Tìm kiếm biểu tượng\\u2026',\n all: 'Tất cả',\n style: 'Kiểu',\n size: 'Kích thước',\n color: 'Màu sắc',\n useColor: ' Dùng màu',\n selectHint: 'Chọn một biểu tượng',\n insertBtn: 'Chèn biểu tượng FA',\n cancelBtn: 'Hủy',\n close: 'Đóng',\n categories: {\n popular: 'Phổ biến',\n interface: 'Giao diện',\n navigation: 'Điều hướng',\n media: 'Phương tiện',\n communication: 'Liên lạc',\n files: 'Tệp tin',\n people: 'Con người',\n objects: 'Đồ vật',\n },\n },\n\n findReplace: {\n findTitle: 'Tìm kiếm',\n findReplaceTitle: 'Tìm & Thay thế',\n findPlaceholder: 'Tìm\\u2026',\n searchAriaLabel: 'Văn bản tìm kiếm',\n caseSensitive: '\\u00a0Phân biệt hoa thường',\n prevBtn: '\\u2190 Trước',\n nextBtn: 'Tiếp \\u2192',\n replacePlaceholder: 'Thay thế bằng\\u2026',\n replaceAriaLabel: 'Thay thế bằng',\n replaceBtn: 'Thay thế',\n replaceAllBtn: 'Thay thế tất cả',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'Phím tắt bàn phím',\n ariaLabel: 'Phím tắt bàn phím',\n close: 'Đóng',\n shortcuts: [\n {\n category: 'Định dạng văn bản',\n items: [\n { keys: 'Ctrl + B', action: 'Đậm' },\n { keys: 'Ctrl + I', action: 'Nghiêng' },\n { keys: 'Ctrl + U', action: 'Gạch chân' },\n { keys: 'Ctrl + K', action: 'Chèn / sửa liên kết' },\n ],\n },\n {\n category: 'Lịch sử',\n items: [\n { keys: 'Ctrl + Z', action: 'Hoàn tác' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Làm lại' },\n ],\n },\n {\n category: 'Chọn & Điều hướng',\n items: [\n { keys: 'Ctrl + A', action: 'Chọn tất cả' },\n { keys: 'Tab', action: 'Tăng thụt đầu dòng / chèn khoảng trắng' },\n { keys: 'Shift + Tab', action: 'Giảm thụt đầu dòng' },\n ],\n },\n {\n category: 'Bảng nhớ tạm',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Dán dưới dạng văn bản thuần' },\n ],\n },\n {\n category: 'Tìm & Thay thế',\n items: [\n { keys: 'Ctrl + F', action: 'Tìm trong tài liệu' },\n { keys: 'Ctrl + H', action: 'Tìm & Thay thế' },\n ],\n },\n {\n category: 'Trình soạn thảo',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Hiện hộp thoại phím tắt' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Cắt',\n copy: 'Sao chép',\n paste: 'Dán',\n bold: 'Đậm',\n italic: 'Nghiêng',\n underline: 'Gạch chân',\n textColor: 'Màu chữ',\n highlightColor: 'Màu nền chữ',\n copyFormat: 'Sao chép định dạng',\n pasteFormat: 'Dán định dạng',\n removeFormat: 'Xóa định dạng',\n link: 'Chèn liên kết',\n image: 'Chèn hình ảnh',\n video: 'Chèn video',\n table: 'Chèn bảng',\n back: 'Quay lại',\n noHighlight: 'Không tô màu',\n customColor: 'Màu tùy chỉnh',\n customColorLabel: 'Tùy ch\\u1ec9nh\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'Kéo để thay đổi kích thước',\n words: (n) => `Từ: ${n}`,\n wordsLimit: (n, max) => `Từ: ${n}/${max}`,\n chars: (n) => `Ký tự: ${n}`,\n charsLimit: (n, max) => `Ký tự: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Hành động liên kết',\n openLink: 'Mở liên kết',\n copyUrl: 'Sao chép URL',\n editLink: 'Sửa liên kết',\n removeLink: 'Xóa liên kết',\n },\n image: {\n ariaLabel: 'Hành động hình ảnh',\n label: 'Hình ảnh',\n floatLeft: 'Nổi trái',\n noFloat: 'Không nổi',\n alignCenter: 'Căn giữa',\n floatRight: 'Nổi phải',\n originalSize: 'Kích thước gốc',\n rotateLeft: 'Xoay trái',\n rotateRight: 'Xoay phải',\n cropImage: 'Cắt ảnh',\n addCaption: 'Thêm / Sửa chú thích',\n deleteImage: 'Xóa hình ảnh',\n },\n code: {\n ariaLabel: 'Hành động khối mã',\n label: 'Mã',\n syntaxLanguage: 'Ngôn ngữ cú pháp',\n syntaxAriaLabel: 'Ngôn ngữ cú pháp',\n copyCode: 'Sao chép mã',\n toggleWordWrap: 'Chuyển đổi xuống dòng',\n enableWordWrap: 'Bật xuống dòng',\n disableWordWrap: 'Tắt xuống dòng',\n convertToParagraph: 'Chuyển thành đoạn văn',\n deleteCodeBlock: 'Xóa khối mã',\n },\n table: {\n ariaLabel: 'Hành động bảng',\n label: 'Bảng',\n selectCells: 'Chọn ô',\n addRowAbove: 'Thêm hàng phía trên',\n addRowBelow: 'Thêm hàng phía dưới',\n deleteRow: 'Xóa hàng',\n addColumnLeft: 'Thêm cột bên trái',\n addColumnRight: 'Thêm cột bên phải',\n deleteColumn: 'Xóa cột',\n mergeCells: 'Gộp ô',\n unmergeCells: 'Tách ô',\n columnWidth: 'Chiều rộng cột',\n rowHeight: 'Chiều cao hàng',\n tableBorderWidth: 'Độ rộng viền bảng',\n deleteTable: 'Xóa bảng',\n columnWidthPx: 'Chiều rộng cột (px)',\n rowHeightPx: 'Chiều cao hàng (px)',\n tableBorderWidthPx: 'Độ rộng viền bảng (px)',\n cancelBtn: 'Hủy',\n applyBtn: 'Áp dụng',\n },\n video: {\n ariaLabel: 'Hành động video',\n label: 'Video',\n floatLeft: 'Nổi trái',\n noFloat: 'Không nổi',\n alignCenter: 'Căn giữa',\n floatRight: 'Nổi phải',\n originalSize: 'Kích thước gốc',\n previewVideo: 'Xem trước',\n exitPreview: 'Thoát xem trước',\n deleteVideo: 'Xóa video',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `Định dạng \"${type}\" không được hỗ trợ hiển thị trên trình duyệt. Vui lòng chuyển đổi sang JPEG, PNG hoặc WebP.`,\n imageSize: (maxSize) =>\n `Tệp hình ảnh quá lớn. Kích thước tối đa cho phép là ${maxSize} MB.`,\n },\n};\n","/**\n * ja.js - 日本語ロケール (Japanese)\n * en.js をベースに上書きするキーのみ定義します。\n * 未定義のキーは resolveLocale による deep-merge で en.js から補完されます。\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const ja = {\n toolbar: {\n bold: '太字 (Ctrl+B)',\n italic: '斜体 (Ctrl+I)',\n underline: '下線 (Ctrl+U)',\n strikethrough: '取り消し線',\n superscript: '上付き文字',\n subscript: '下付き文字',\n alignLeft: '左揃え',\n alignCenter: '中央揃え',\n alignRight: '右揃え',\n alignJustify: '両端揃え',\n ul: '箇条書きリスト',\n ol: '番号付きリスト',\n checklist: 'チェックリスト',\n indent: 'インデントを増やす',\n outdent: 'インデントを減らす',\n undo: '元に戻す (Ctrl+Z)',\n redo: 'やり直す (Ctrl+Y)',\n hr: '水平線',\n link: 'リンクを挿入',\n image: '画像を挿入',\n video: '動画を挿入',\n emoji: '絵文字を挿入',\n icon: 'FAアイコンを挿入',\n table: 'テーブルを挿入',\n fontSize: 'フォントサイズ',\n fontSizePlaceholder: 'サイズ',\n removeFormat: '書式をリセット',\n direction: '文字方向を切り替え (LTR / RTL)',\n fontFamily: 'フォント',\n paragraphStyle: '段落スタイル',\n paragraphStylePlaceholder: 'スタイル',\n lineHeight: '行の高さ',\n lineHeightPlaceholder: '\\u2195 行間',\n codeview: 'HTMLソースを表示',\n fullscreen: '全画面表示',\n shortcuts: 'キーボードショートカット (Ctrl+Shift+/)',\n find: '検索 (Ctrl+F)',\n findReplace: '検索と置換 (Ctrl+H)',\n inlineCode: 'インラインコード (Ctrl+`)',\n print: '印刷',\n foreColor: '文字色',\n backColor: 'ハイライト色',\n chooseTextColor: '文字色を選択',\n chooseHighlightColor: 'ハイライト色を選択',\n customColor: 'カスタムカラー',\n insertTableLabel: 'テーブルを挿入',\n paragraphItems: {\n p: '標準',\n blockquote: '引用',\n pre: 'コード',\n },\n },\n\n linkDialog: {\n ariaLabel: 'リンクを挿入',\n title: 'リンクを挿入',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: '表示テキスト',\n textPlaceholder: 'リンクテキスト',\n openInNewTab: '新しいタブで開く',\n insertBtn: '挿入',\n cancelBtn: 'キャンセル',\n },\n\n imageDialog: {\n ariaLabel: '画像を挿入',\n title: '画像を挿入',\n imageUrl: '画像URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: '代替テキスト',\n altPlaceholder: '画像の説明',\n alignment: '配置',\n alignNone: 'なし',\n alignLeft: '左',\n alignCenter: '中央',\n alignRight: '右',\n uploadLabel: 'ファイルをアップロード',\n insertBtn: '挿入',\n cancelBtn: 'キャンセル',\n },\n\n videoDialog: {\n ariaLabel: '動画を挿入',\n title: '動画を挿入',\n videoUrl: '動画URL',\n urlPlaceholder: 'YouTube、Vimeo、または直接動画URL',\n widthLabel: '幅 (px)',\n widthPlaceholder: '560',\n insertBtn: '挿入',\n cancelBtn: 'キャンセル',\n detected: (type) => `検出: ${type}`,\n unknownFormat: '不明な形式 \\u2014 直接動画埋め込みを試みます',\n invalidUrl: 'URLが無効です \\u2014 有効な動画URLを入力してください。',\n },\n\n emojiDialog: {\n ariaLabel: '絵文字を挿入',\n title: '絵文字を挿入',\n searchPlaceholder: '絵文字を検索\\u2026',\n all: 'すべて',\n cancelBtn: 'キャンセル',\n close: '閉じる',\n categories: {\n smileys: '顔文字',\n people: '人物',\n animals: '動物',\n food: '食べ物',\n travel: '旅行',\n objects: 'モノ',\n symbols: '記号',\n },\n },\n\n iconDialog: {\n ariaLabel: 'FAアイコンを挿入',\n title: 'FAアイコンを挿入',\n searchPlaceholder: 'アイコンを検索\\u2026',\n all: 'すべて',\n style: 'スタイル',\n size: 'サイズ',\n color: 'カラー',\n useColor: ' カラーを使用',\n selectHint: 'アイコンを選択してください',\n insertBtn: 'FAアイコンを挿入',\n cancelBtn: 'キャンセル',\n close: '閉じる',\n categories: {\n popular: '人気',\n interface: 'インターフェース',\n navigation: 'ナビゲーション',\n media: 'メディア',\n communication: '通信',\n files: 'ファイル',\n people: '人物',\n objects: 'モノ',\n },\n },\n\n findReplace: {\n findTitle: '検索',\n findReplaceTitle: '検索と置換',\n findPlaceholder: '検索\\u2026',\n searchAriaLabel: '検索テキスト',\n caseSensitive: '\\u00a0大文字/小文字を区別',\n prevBtn: '\\u2190 前へ',\n nextBtn: '次へ \\u2192',\n replacePlaceholder: '置換後\\u2026',\n replaceAriaLabel: '置換後のテキスト',\n replaceBtn: '置換',\n replaceAllBtn: 'すべて置換',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'キーボードショートカット',\n ariaLabel: 'キーボードショートカット',\n close: '閉じる',\n shortcuts: [\n {\n category: 'テキスト書式',\n items: [\n { keys: 'Ctrl + B', action: '太字' },\n { keys: 'Ctrl + I', action: '斜体' },\n { keys: 'Ctrl + U', action: '下線' },\n { keys: 'Ctrl + K', action: 'リンクの挿入 / 編集' },\n ],\n },\n {\n category: '履歴',\n items: [\n { keys: 'Ctrl + Z', action: '元に戻す' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'やり直す' },\n ],\n },\n {\n category: '選択と移動',\n items: [\n { keys: 'Ctrl + A', action: 'すべて選択' },\n { keys: 'Tab', action: 'インデント増加 / スペース挿入' },\n { keys: 'Shift + Tab', action: 'インデント減少' },\n ],\n },\n {\n category: 'クリップボード',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'プレーンテキストとして貼り付け' },\n ],\n },\n {\n category: '検索と置換',\n items: [\n { keys: 'Ctrl + F', action: '文書内を検索' },\n { keys: 'Ctrl + H', action: '検索と置換' },\n ],\n },\n {\n category: 'エディター',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'ショートカットダイアログを表示' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: '切り取り',\n copy: 'コピー',\n paste: '貼り付け',\n bold: '太字',\n italic: '斜体',\n underline: '下線',\n textColor: '文字色',\n highlightColor: 'ハイライト色',\n copyFormat: '書式をコピー',\n pasteFormat: '書式を貼り付け',\n removeFormat: '書式をリセット',\n link: 'リンクを挿入',\n image: '画像を挿入',\n video: '動画を挿入',\n table: 'テーブルを挿入',\n back: '戻る',\n noHighlight: 'ハイライトなし',\n customColor: 'カスタムカラー',\n customColorLabel: 'カスタム\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'ドラッグしてリサイズ',\n words: (n) => `単語数: ${n}`,\n wordsLimit: (n, max) => `単語数: ${n}/${max}`,\n chars: (n) => `文字数: ${n}`,\n charsLimit: (n, max) => `文字数: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'リンク操作',\n openLink: 'リンクを開く',\n copyUrl: 'URLをコピー',\n editLink: 'リンクを編集',\n removeLink: 'リンクを削除',\n },\n image: {\n ariaLabel: '画像操作',\n label: '画像',\n floatLeft: '左に回り込み',\n noFloat: '回り込みなし',\n alignCenter: '中央揃え',\n floatRight: '右に回り込み',\n originalSize: '元のサイズ',\n rotateLeft: '左に回転',\n rotateRight: '右に回転',\n cropImage: '画像をトリミング',\n addCaption: 'キャプションを追加 / 編集',\n deleteImage: '画像を削除',\n },\n code: {\n ariaLabel: 'コードブロック操作',\n label: 'コード',\n syntaxLanguage: '言語',\n syntaxAriaLabel: '構文言語',\n copyCode: 'コードをコピー',\n toggleWordWrap: '折り返しを切り替え',\n enableWordWrap: '折り返しを有効にする',\n disableWordWrap: '折り返しを無効にする',\n convertToParagraph: '段落に変換',\n deleteCodeBlock: 'コードブロックを削除',\n },\n table: {\n ariaLabel: 'テーブル操作',\n label: 'テーブル',\n selectCells: 'セルを選択',\n addRowAbove: '上に行を追加',\n addRowBelow: '下に行を追加',\n deleteRow: '行を削除',\n addColumnLeft: '左に列を追加',\n addColumnRight: '右に列を追加',\n deleteColumn: '列を削除',\n mergeCells: 'セルを結合',\n unmergeCells: 'セルの結合を解除',\n columnWidth: '列幅',\n rowHeight: '行の高さ',\n tableBorderWidth: 'テーブルの枠幅',\n deleteTable: 'テーブルを削除',\n columnWidthPx: '列幅 (px)',\n rowHeightPx: '行の高さ (px)',\n tableBorderWidthPx: 'テーブルの枠幅 (px)',\n cancelBtn: 'キャンセル',\n applyBtn: '適用',\n },\n video: {\n ariaLabel: '動画操作',\n label: '動画',\n floatLeft: '左に回り込み',\n noFloat: '回り込みなし',\n alignCenter: '中央揃え',\n floatRight: '右に回り込み',\n originalSize: '元のサイズ',\n previewVideo: 'プレビュー',\n exitPreview: 'プレビューを終了',\n deleteVideo: '動画を削除',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `形式 \"${type}\" はブラウザでの表示をサポートしていません。JPEG、PNG、または WebP に変換してください。`,\n imageSize: (maxSize) =>\n `画像ファイルが大きすぎます。最大許容サイズは ${maxSize} MB です。`,\n },\n};\n","/**\n * zh.js - 简体中文 (Simplified Chinese) locale\n * 仅包含与 en.js 不同的键值。\n * resolveLocale 会将本文件与 en.js 进行深度合并。\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const zh = {\n toolbar: {\n bold: '粗体 (Ctrl+B)',\n italic: '斜体 (Ctrl+I)',\n underline: '下划线 (Ctrl+U)',\n strikethrough: '删除线',\n superscript: '上标',\n subscript: '下标',\n alignLeft: '左对齐',\n alignCenter: '居中',\n alignRight: '右对齐',\n alignJustify: '两端对齐',\n ul: '无序列表',\n ol: '有序列表',\n checklist: '待办列表',\n indent: '增加缩进',\n outdent: '减少缩进',\n undo: '撤销 (Ctrl+Z)',\n redo: '重做 (Ctrl+Y)',\n hr: '水平分割线',\n link: '插入链接',\n image: '插入图片',\n video: '插入视频',\n emoji: '插入表情',\n icon: '插入 FA 图标',\n table: '插入表格',\n fontSize: '字号',\n fontSizePlaceholder: '大小',\n removeFormat: '清除格式',\n direction: '切换文字方向 (LTR / RTL)',\n fontFamily: '字体',\n paragraphStyle: '段落样式',\n paragraphStylePlaceholder: '样式',\n lineHeight: '行高',\n lineHeightPlaceholder: '\\u2195 行距',\n codeview: '查看 HTML 源码',\n fullscreen: '全屏',\n shortcuts: '键盘快捷键 (Ctrl+Shift+/)',\n find: '搜索 (Ctrl+F)',\n findReplace: '查找和替换 (Ctrl+H)',\n inlineCode: '行内代码 (Ctrl+`)',\n print: '打印',\n foreColor: '文字颜色',\n backColor: '高亮颜色',\n chooseTextColor: '选择文字颜色',\n chooseHighlightColor: '选择高亮颜色',\n customColor: '自定义颜色',\n insertTableLabel: '插入表格',\n paragraphItems: {\n p: '正文',\n blockquote: '引用',\n pre: '代码',\n },\n },\n\n linkDialog: {\n ariaLabel: '插入链接',\n title: '插入链接',\n url: '链接地址',\n urlPlaceholder: 'https://',\n displayText: '显示文字',\n textPlaceholder: '链接文字',\n openInNewTab: '在新标签页中打开',\n insertBtn: '插入',\n cancelBtn: '取消',\n },\n\n imageDialog: {\n ariaLabel: '插入图片',\n title: '插入图片',\n imageUrl: '图片地址',\n urlPlaceholder: 'https://example.com/image.png',\n altText: '替代文字',\n altPlaceholder: '图片描述',\n alignment: '对齐方式',\n alignNone: '无',\n alignLeft: '左',\n alignCenter: '居中',\n alignRight: '右',\n uploadLabel: '或上传文件',\n insertBtn: '插入',\n cancelBtn: '取消',\n },\n\n videoDialog: {\n ariaLabel: '插入视频',\n title: '插入视频',\n videoUrl: '视频地址',\n urlPlaceholder: 'YouTube、Vimeo 或直接 .mp4 链接',\n widthLabel: '宽度 (px)',\n widthPlaceholder: '560',\n insertBtn: '插入',\n cancelBtn: '取消',\n detected: (type) => `已识别: ${type}`,\n unknownFormat: '未知格式 \\u2014 将尝试直接嵌入视频',\n invalidUrl: 'URL 无效 \\u2014 请输入有效的视频链接。',\n },\n\n emojiDialog: {\n ariaLabel: '插入表情',\n title: '插入表情',\n searchPlaceholder: '搜索表情\\u2026',\n all: '全部',\n cancelBtn: '取消',\n close: '关闭',\n categories: {\n smileys: '笑脸',\n people: '人物',\n animals: '动物',\n food: '食物',\n travel: '旅行',\n objects: '物品',\n symbols: '符号',\n },\n },\n\n iconDialog: {\n ariaLabel: '插入 FA 图标',\n title: '插入 FA 图标',\n searchPlaceholder: '搜索图标\\u2026',\n all: '全部',\n style: '样式',\n size: '大小',\n color: '颜色',\n useColor: ' 使用颜色',\n selectHint: '请选择一个图标',\n insertBtn: '插入 FA 图标',\n cancelBtn: '取消',\n close: '关闭',\n categories: {\n popular: '热门',\n interface: '界面',\n navigation: '导航',\n media: '媒体',\n communication: '通讯',\n files: '文件',\n people: '人物',\n objects: '物品',\n },\n },\n\n findReplace: {\n findTitle: '搜索',\n findReplaceTitle: '查找和替换',\n findPlaceholder: '查找\\u2026',\n searchAriaLabel: '搜索文字',\n caseSensitive: '\\u00a0区分大小写',\n prevBtn: '\\u2190 上一个',\n nextBtn: '下一个 \\u2192',\n replacePlaceholder: '替换为\\u2026',\n replaceAriaLabel: '替换为',\n replaceBtn: '替换',\n replaceAllBtn: '全部替换',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: '键盘快捷键',\n ariaLabel: '键盘快捷键',\n close: '关闭',\n shortcuts: [\n {\n category: '文字格式',\n items: [\n { keys: 'Ctrl + B', action: '粗体' },\n { keys: 'Ctrl + I', action: '斜体' },\n { keys: 'Ctrl + U', action: '下划线' },\n { keys: 'Ctrl + K', action: '插入 / 编辑链接' },\n ],\n },\n {\n category: '历史记录',\n items: [\n { keys: 'Ctrl + Z', action: '撤销' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: '重做' },\n ],\n },\n {\n category: '选择与导航',\n items: [\n { keys: 'Ctrl + A', action: '全选' },\n { keys: 'Tab', action: '增加缩进 / 插入空格' },\n { keys: 'Shift + Tab', action: '减少缩进' },\n ],\n },\n {\n category: '剪贴板',\n items: [\n { keys: 'Ctrl + Shift + V', action: '粘贴为纯文本' },\n ],\n },\n {\n category: '查找和替换',\n items: [\n { keys: 'Ctrl + F', action: '在文档中搜索' },\n { keys: 'Ctrl + H', action: '查找和替换' },\n ],\n },\n {\n category: '编辑器',\n items: [\n { keys: 'Ctrl + Shift + /', action: '显示快捷键对话框' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: '剪切',\n copy: '复制',\n paste: '粘贴',\n bold: '粗体',\n italic: '斜体',\n underline: '下划线',\n textColor: '文字颜色',\n highlightColor: '高亮颜色',\n copyFormat: '复制格式',\n pasteFormat: '粘贴格式',\n removeFormat: '清除格式',\n link: '插入链接',\n image: '插入图片',\n video: '插入视频',\n table: '插入表格',\n back: '返回',\n noHighlight: '无高亮',\n customColor: '自定义颜色',\n customColorLabel: '自定义\\u2026',\n },\n\n statusbar: {\n resizeHandle: '拖动以调整大小',\n words: (n) => `字数: ${n}`,\n wordsLimit: (n, max) => `字数: ${n}/${max}`,\n chars: (n) => `字符数: ${n}`,\n charsLimit: (n, max) => `字符数: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: '链接操作',\n openLink: '打开链接',\n copyUrl: '复制 URL',\n editLink: '编辑链接',\n removeLink: '删除链接',\n },\n image: {\n ariaLabel: '图片操作',\n label: '图片',\n floatLeft: '左浮动',\n noFloat: '不浮动',\n alignCenter: '居中对齐',\n floatRight: '右浮动',\n originalSize: '原始尺寸',\n rotateLeft: '向左旋转',\n rotateRight: '向右旋转',\n cropImage: '裁剪图片',\n addCaption: '添加 / 编辑说明',\n deleteImage: '删除图片',\n },\n code: {\n ariaLabel: '代码块操作',\n label: '代码',\n syntaxLanguage: '语法语言',\n syntaxAriaLabel: '语法语言',\n copyCode: '复制代码',\n toggleWordWrap: '切换自动换行',\n enableWordWrap: '启用自动换行',\n disableWordWrap: '禁用自动换行',\n convertToParagraph: '转换为段落',\n deleteCodeBlock: '删除代码块',\n },\n table: {\n ariaLabel: '表格操作',\n label: '表格',\n selectCells: '选择单元格',\n addRowAbove: '在上方插入行',\n addRowBelow: '在下方插入行',\n deleteRow: '删除行',\n addColumnLeft: '在左侧插入列',\n addColumnRight: '在右侧插入列',\n deleteColumn: '删除列',\n mergeCells: '合并单元格',\n unmergeCells: '拆分单元格',\n columnWidth: '列宽',\n rowHeight: '行高',\n tableBorderWidth: '表格边框宽度',\n deleteTable: '删除表格',\n columnWidthPx: '列宽 (px)',\n rowHeightPx: '行高 (px)',\n tableBorderWidthPx: '表格边框宽度 (px)',\n cancelBtn: '取消',\n applyBtn: '应用',\n },\n video: {\n ariaLabel: '视频操作',\n label: '视频',\n floatLeft: '左浮动',\n noFloat: '不浮动',\n alignCenter: '居中对齐',\n floatRight: '右浮动',\n originalSize: '原始尺寸',\n previewVideo: '预览视频',\n exitPreview: '退出预览',\n deleteVideo: '删除视频',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `格式 \"${type}\" 不支持在浏览器中显示。请转换为 JPEG、PNG 或 WebP。`,\n imageSize: (maxSize) =>\n `图片文件过大。最大允许大小为 ${maxSize} MB。`,\n },\n};\n","/**\n * fr.js - Français (French) locale\n * Seules les clés différentes de en.js sont définies ici.\n * Les clés manquantes sont complétées par en.js via deep-merge dans resolveLocale.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const fr = {\n toolbar: {\n bold: 'Gras (Ctrl+B)',\n italic: 'Italique (Ctrl+I)',\n underline: 'Souligné (Ctrl+U)',\n strikethrough: 'Barré',\n superscript: 'Exposant',\n subscript: 'Indice',\n alignLeft: 'Aligner à gauche',\n alignCenter: 'Centrer',\n alignRight: 'Aligner à droite',\n alignJustify: 'Justifier',\n ul: 'Liste à puces',\n ol: 'Liste numérotée',\n checklist: 'Liste de tâches',\n indent: 'Augmenter le retrait',\n outdent: 'Diminuer le retrait',\n undo: 'Annuler (Ctrl+Z)',\n redo: 'Rétablir (Ctrl+Y)',\n hr: 'Ligne horizontale',\n link: 'Insérer un lien',\n image: 'Insérer une image',\n video: 'Insérer une vidéo',\n emoji: 'Insérer un emoji',\n icon: 'Insérer une icône FA',\n table: 'Insérer un tableau',\n fontSize: 'Taille de police',\n fontSizePlaceholder: 'Taille',\n removeFormat: 'Effacer la mise en forme',\n direction: 'Basculer la direction du texte (LTR / RTL)',\n fontFamily: 'Police',\n paragraphStyle: 'Style de paragraphe',\n paragraphStylePlaceholder: 'Style',\n lineHeight: 'Interligne',\n lineHeightPlaceholder: '\\u2195 Ligne',\n codeview: 'Afficher le code HTML',\n fullscreen: 'Plein écran',\n shortcuts: 'Raccourcis clavier (Ctrl+Shift+/)',\n find: 'Rechercher (Ctrl+F)',\n findReplace: 'Rechercher et remplacer (Ctrl+H)',\n inlineCode: 'Code inline (Ctrl+`)',\n print: 'Imprimer',\n foreColor: 'Couleur du texte',\n backColor: 'Couleur de surbrillance',\n chooseTextColor: 'Choisir la couleur du texte',\n chooseHighlightColor: 'Choisir la couleur de surbrillance',\n customColor: 'Couleur personnalisée',\n insertTableLabel: 'Insérer un tableau',\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Citation',\n pre: 'Code',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Insérer un lien',\n title: 'Insérer un lien',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Texte affiché',\n textPlaceholder: 'Texte du lien',\n openInNewTab: 'Ouvrir dans un nouvel onglet',\n insertBtn: 'Insérer',\n cancelBtn: 'Annuler',\n },\n\n imageDialog: {\n ariaLabel: 'Insérer une image',\n title: 'Insérer une image',\n imageUrl: 'URL de l\\'image',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Texte alternatif',\n altPlaceholder: 'Description de l\\'image',\n alignment: 'Alignement',\n alignNone: 'Aucun',\n alignLeft: 'Gauche',\n alignCenter: 'Centre',\n alignRight: 'Droite',\n uploadLabel: 'Ou téléverser un fichier',\n insertBtn: 'Insérer',\n cancelBtn: 'Annuler',\n },\n\n videoDialog: {\n ariaLabel: 'Insérer une vidéo',\n title: 'Insérer une vidéo',\n videoUrl: 'URL de la vidéo',\n urlPlaceholder: 'YouTube, Vimeo ou URL .mp4 directe',\n widthLabel: 'Largeur (px)',\n widthPlaceholder: '560',\n insertBtn: 'Insérer',\n cancelBtn: 'Annuler',\n detected: (type) => `Détecté\\u00a0: ${type}`,\n unknownFormat: 'Format inconnu \\u2014 tentative d\\'intégration directe',\n invalidUrl: 'URL invalide \\u2014 veuillez saisir un lien vidéo valide.',\n },\n\n emojiDialog: {\n ariaLabel: 'Insérer un emoji',\n title: 'Insérer un emoji',\n searchPlaceholder: 'Rechercher des emojis\\u2026',\n all: 'Tout',\n cancelBtn: 'Annuler',\n close: 'Fermer',\n categories: {\n smileys: 'Smileys',\n people: 'Personnes',\n animals: 'Animaux',\n food: 'Nourriture',\n travel: 'Voyage',\n objects: 'Objets',\n symbols: 'Symboles',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Insérer une icône FA',\n title: 'Insérer une icône FA',\n searchPlaceholder: 'Rechercher des icônes\\u2026',\n all: 'Tout',\n style: 'Style',\n size: 'Taille',\n color: 'Couleur',\n useColor: ' Utiliser la couleur',\n selectHint: 'Sélectionner une icône',\n insertBtn: 'Insérer une icône FA',\n cancelBtn: 'Annuler',\n close: 'Fermer',\n categories: {\n popular: 'Populaire',\n interface: 'Interface',\n navigation: 'Navigation',\n media: 'Média',\n communication: 'Communication',\n files: 'Fichiers',\n people: 'Personnes',\n objects: 'Objets',\n },\n },\n\n findReplace: {\n findTitle: 'Rechercher',\n findReplaceTitle: 'Rechercher et remplacer',\n findPlaceholder: 'Rechercher\\u2026',\n searchAriaLabel: 'Texte à rechercher',\n caseSensitive: '\\u00a0Respecter la casse',\n prevBtn: '\\u2190 Préc.',\n nextBtn: 'Suiv. \\u2192',\n replacePlaceholder: 'Remplacer par\\u2026',\n replaceAriaLabel: 'Remplacer par',\n replaceBtn: 'Remplacer',\n replaceAllBtn: 'Tout remplacer',\n close: '\\u00d7',\n },\n\n shortcutsDialog: {\n title: 'Raccourcis clavier',\n ariaLabel: 'Raccourcis clavier',\n close: 'Fermer',\n shortcuts: [\n {\n category: 'Mise en forme du texte',\n items: [\n { keys: 'Ctrl + B', action: 'Gras' },\n { keys: 'Ctrl + I', action: 'Italique' },\n { keys: 'Ctrl + U', action: 'Souligné' },\n { keys: 'Ctrl + K', action: 'Insérer / modifier un lien' },\n ],\n },\n {\n category: 'Historique',\n items: [\n { keys: 'Ctrl + Z', action: 'Annuler' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Rétablir' },\n ],\n },\n {\n category: 'Sélection et navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Tout sélectionner' },\n { keys: 'Tab', action: 'Augmenter le retrait / insérer des espaces' },\n { keys: 'Shift + Tab', action: 'Diminuer le retrait' },\n ],\n },\n {\n category: 'Presse-papiers',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Coller en texte brut' },\n ],\n },\n {\n category: 'Rechercher et remplacer',\n items: [\n { keys: 'Ctrl + F', action: 'Rechercher dans le document' },\n { keys: 'Ctrl + H', action: 'Rechercher et remplacer' },\n ],\n },\n {\n category: 'Éditeur',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Afficher les raccourcis clavier' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Couper',\n copy: 'Copier',\n paste: 'Coller',\n bold: 'Gras',\n italic: 'Italique',\n underline: 'Souligné',\n textColor: 'Couleur du texte',\n highlightColor: 'Couleur de surbrillance',\n copyFormat: 'Copier la mise en forme',\n pasteFormat: 'Coller la mise en forme',\n removeFormat: 'Effacer la mise en forme',\n link: 'Insérer un lien',\n image: 'Insérer une image',\n video: 'Insérer une vidéo',\n table: 'Insérer un tableau',\n back: 'Retour',\n noHighlight: 'Sans surbrillance',\n customColor: 'Couleur personnalisée',\n customColorLabel: 'Personnaliser\\u2026',\n },\n\n statusbar: {\n resizeHandle: 'Faire glisser pour redimensionner',\n words: (n) => `Mots\\u00a0: ${n}`,\n wordsLimit: (n, max) => `Mots\\u00a0: ${n}/${max}`,\n chars: (n) => `Caractères\\u00a0: ${n}`,\n charsLimit: (n, max) => `Caractères\\u00a0: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Actions du lien',\n openLink: 'Ouvrir le lien',\n copyUrl: 'Copier l\\'URL',\n editLink: 'Modifier le lien',\n removeLink: 'Supprimer le lien',\n },\n image: {\n ariaLabel: 'Actions de l\\'image',\n label: 'Image',\n floatLeft: 'Flottant à gauche',\n noFloat: 'Sans flottant',\n alignCenter: 'Centré',\n floatRight: 'Flottant à droite',\n originalSize: 'Taille originale',\n rotateLeft: 'Rotation à gauche',\n rotateRight: 'Rotation à droite',\n cropImage: 'Recadrer l\\'image',\n addCaption: 'Ajouter / modifier la légende',\n deleteImage: 'Supprimer l\\'image',\n },\n code: {\n ariaLabel: 'Actions du bloc de code',\n label: 'Code',\n syntaxLanguage: 'Langage de syntaxe',\n syntaxAriaLabel: 'Langage de syntaxe',\n copyCode: 'Copier le code',\n toggleWordWrap: 'Activer/désactiver le retour à la ligne',\n enableWordWrap: 'Activer le retour à la ligne',\n disableWordWrap: 'Désactiver le retour à la ligne',\n convertToParagraph: 'Convertir en paragraphe',\n deleteCodeBlock: 'Supprimer le bloc de code',\n },\n table: {\n ariaLabel: 'Actions du tableau',\n label: 'Tableau',\n selectCells: 'Sélectionner des cellules',\n addRowAbove: 'Ajouter une ligne au-dessus',\n addRowBelow: 'Ajouter une ligne en-dessous',\n deleteRow: 'Supprimer la ligne',\n addColumnLeft: 'Ajouter une colonne à gauche',\n addColumnRight: 'Ajouter une colonne à droite',\n deleteColumn: 'Supprimer la colonne',\n mergeCells: 'Fusionner les cellules',\n unmergeCells: 'Scinder les cellules',\n columnWidth: 'Largeur de colonne',\n rowHeight: 'Hauteur de ligne',\n tableBorderWidth: 'Épaisseur des bordures',\n deleteTable: 'Supprimer le tableau',\n columnWidthPx: 'Largeur de colonne (px)',\n rowHeightPx: 'Hauteur de ligne (px)',\n tableBorderWidthPx: 'Épaisseur des bordures (px)',\n cancelBtn: 'Annuler',\n applyBtn: 'Appliquer',\n },\n video: {\n ariaLabel: 'Actions de la vidéo',\n label: 'Vidéo',\n floatLeft: 'Flottant à gauche',\n noFloat: 'Sans flottant',\n alignCenter: 'Centré',\n floatRight: 'Flottant à droite',\n originalSize: 'Taille originale',\n previewVideo: 'Aperçu',\n exitPreview: 'Quitter l\\'aperçu',\n deleteVideo: 'Supprimer la vidéo',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `Le format \"${type}\" n'est pas pris en charge par le navigateur. Veuillez le convertir en JPEG, PNG ou WebP.`,\n imageSize: (maxSize) =>\n `Le fichier image est trop volumineux. La taille maximale autorisée est de ${maxSize}\\u00a0Mo.`,\n },\n};\n","/**\n * de.js - German locale\n * Deep-merged over en.js; only keys that differ from English are listed.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const de = {\n toolbar: {\n bold: 'Fett (Ctrl+B)',\n italic: 'Kursiv (Ctrl+I)',\n underline: 'Unterstrichen (Ctrl+U)',\n strikethrough: 'Durchgestrichen',\n superscript: 'Hochgestellt',\n subscript: 'Tiefgestellt',\n alignLeft: 'Linksbündig',\n alignCenter: 'Zentriert',\n alignRight: 'Rechtsbündig',\n alignJustify: 'Blocksatz',\n ul: 'Ungeordnete Liste',\n ol: 'Geordnete Liste',\n checklist: 'Checkliste',\n indent: 'Einzug vergrößern',\n outdent: 'Einzug verkleinern',\n undo: 'Rückgängig (Ctrl+Z)',\n redo: 'Wiederholen (Ctrl+Y)',\n hr: 'Horizontale Linie',\n link: 'Link einfügen',\n image: 'Bild einfügen',\n video: 'Video einfügen',\n emoji: 'Emoji einfügen',\n icon: 'FA-Symbol einfügen',\n table: 'Tabelle einfügen',\n fontSize: 'Schriftgröße',\n fontSizePlaceholder: 'Größe',\n removeFormat: 'Formatierung entfernen',\n direction: 'Textrichtung umschalten (LTR / RTL)',\n fontFamily: 'Schriftart',\n paragraphStyle: 'Absatzstil',\n paragraphStylePlaceholder: 'Stil',\n lineHeight: 'Zeilenhöhe',\n lineHeightPlaceholder: '↕ Zeile',\n codeview: 'HTML-Code-Ansicht',\n fullscreen: 'Vollbild',\n shortcuts: 'Tastenkürzel (Ctrl+Shift+/)',\n find: 'Suchen (Ctrl+F)',\n findReplace: 'Suchen & Ersetzen (Ctrl+H)',\n inlineCode: 'Inline-Code (Ctrl+`)',\n print: 'Drucken',\n foreColor: 'Textfarbe',\n backColor: 'Hervorhebungsfarbe',\n chooseTextColor: 'Textfarbe auswählen',\n chooseHighlightColor: 'Hervorhebungsfarbe auswählen',\n customColor: 'Benutzerdefinierte Farbe',\n insertTableLabel: 'Tabelle einfügen',\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Zitat',\n pre: 'Code',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Link einfügen',\n title: 'Link einfügen',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Anzeigetext',\n textPlaceholder: 'Linktext',\n openInNewTab: 'In neuem Tab öffnen',\n insertBtn: 'Einfügen',\n cancelBtn: 'Abbrechen',\n },\n\n imageDialog: {\n ariaLabel: 'Bild einfügen',\n title: 'Bild einfügen',\n imageUrl: 'Bild-URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Alt-Text',\n altPlaceholder: 'Bild beschreiben',\n alignment: 'Ausrichtung',\n alignNone: 'Keine',\n alignLeft: 'Links',\n alignCenter: 'Mitte',\n alignRight: 'Rechts',\n uploadLabel: 'Oder Datei hochladen',\n insertBtn: 'Einfügen',\n cancelBtn: 'Abbrechen',\n },\n\n videoDialog: {\n ariaLabel: 'Video einfügen',\n title: 'Video einfügen',\n videoUrl: 'Video-URL',\n urlPlaceholder: 'YouTube, Vimeo oder direkte .mp4-URL',\n widthLabel: 'Breite (px)',\n widthPlaceholder: '560',\n insertBtn: 'Einfügen',\n cancelBtn: 'Abbrechen',\n detected: (type) => `Erkannt: ${type}`,\n unknownFormat: 'Unbekanntes Format — direktes Video-Einbetten wird versucht',\n invalidUrl: 'Ungültige URL — bitte geben Sie einen gültigen Videolink ein.',\n },\n\n emojiDialog: {\n ariaLabel: 'Emoji einfügen',\n title: 'Emoji einfügen',\n searchPlaceholder: 'Emojis suchen…',\n all: 'Alle',\n cancelBtn: 'Abbrechen',\n close: 'Schließen',\n categories: {\n smileys: 'Smileys',\n people: 'Menschen',\n animals: 'Tiere',\n food: 'Essen',\n travel: 'Reisen',\n objects: 'Objekte',\n symbols: 'Symbole',\n },\n },\n\n iconDialog: {\n ariaLabel: 'FA-Symbol einfügen',\n title: 'FA-Symbol einfügen',\n searchPlaceholder: 'Symbole suchen…',\n all: 'Alle',\n style: 'Stil',\n size: 'Größe',\n color: 'Farbe',\n useColor: ' Farbe verwenden',\n selectHint: 'Symbol auswählen',\n insertBtn: 'FA-Symbol einfügen',\n cancelBtn: 'Abbrechen',\n close: 'Schließen',\n categories: {\n popular: 'Beliebt',\n interface: 'Benutzeroberfläche',\n navigation: 'Navigation',\n media: 'Medien',\n communication: 'Kommunikation',\n files: 'Dateien',\n people: 'Menschen',\n objects: 'Objekte',\n },\n },\n\n findReplace: {\n findTitle: 'Suchen',\n findReplaceTitle: 'Suchen & Ersetzen',\n findPlaceholder: 'Suchen…',\n searchAriaLabel: 'Suchtext',\n caseSensitive: '\\u00a0Groß-/Kleinschreibung',\n prevBtn: '← Zurück',\n nextBtn: 'Weiter →',\n replacePlaceholder: 'Ersetzen durch…',\n replaceAriaLabel: 'Ersetzen durch',\n replaceBtn: 'Ersetzen',\n replaceAllBtn: 'Alle ersetzen',\n close: '×',\n },\n\n shortcutsDialog: {\n title: 'Tastenkürzel',\n ariaLabel: 'Tastenkürzel',\n close: 'Schließen',\n shortcuts: [\n {\n category: 'Textformatierung',\n items: [\n { keys: 'Ctrl + B', action: 'Fett' },\n { keys: 'Ctrl + I', action: 'Kursiv' },\n { keys: 'Ctrl + U', action: 'Unterstrichen' },\n { keys: 'Ctrl + K', action: 'Link einfügen / bearbeiten' },\n ],\n },\n {\n category: 'Verlauf',\n items: [\n { keys: 'Ctrl + Z', action: 'Rückgängig' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Wiederholen' },\n ],\n },\n {\n category: 'Auswahl & Navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Alles auswählen' },\n { keys: 'Tab', action: 'Listenebene erhöhen / Leerzeichen einfügen' },\n { keys: 'Shift + Tab', action: 'Listenebene verringern' },\n ],\n },\n {\n category: 'Zwischenablage',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Als einfachen Text einfügen' },\n ],\n },\n {\n category: 'Suchen & Ersetzen',\n items: [\n { keys: 'Ctrl + F', action: 'Im Dokument suchen' },\n { keys: 'Ctrl + H', action: 'Suchen & Ersetzen' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Diesen Tastenkürzel-Dialog anzeigen' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Ausschneiden',\n copy: 'Kopieren',\n paste: 'Einfügen',\n bold: 'Fett',\n italic: 'Kursiv',\n underline: 'Unterstrichen',\n textColor: 'Textfarbe',\n highlightColor: 'Hervorhebungsfarbe',\n copyFormat: 'Format kopieren',\n pasteFormat: 'Format einfügen',\n removeFormat: 'Formatierung entfernen',\n link: 'Link einfügen',\n image: 'Bild einfügen',\n video: 'Video einfügen',\n table: 'Tabelle einfügen',\n back: 'Zurück',\n noHighlight: 'Keine Hervorhebung',\n customColor: 'Benutzerdefinierte Farbe',\n customColorLabel: 'Benutzerdefiniert…',\n },\n\n statusbar: {\n resizeHandle: 'Editor-Größe ändern',\n words: (n) => `Wörter: ${n}`,\n wordsLimit: (n, max) => `Wörter: ${n}/${max}`,\n chars: (n) => `Zeichen: ${n}`,\n charsLimit: (n, max) => `Zeichen: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Link-Aktionen',\n openLink: 'Link öffnen',\n copyUrl: 'URL kopieren',\n editLink: 'Link bearbeiten',\n removeLink: 'Link entfernen',\n },\n image: {\n ariaLabel: 'Bild-Aktionen',\n label: 'Bild',\n floatLeft: 'Links umfließen',\n noFloat: 'Kein Umfluss',\n alignCenter: 'Zentriert',\n floatRight: 'Rechts umfließen',\n originalSize: 'Originalgröße',\n rotateLeft: 'Links drehen',\n rotateRight: 'Rechts drehen',\n cropImage: 'Bild zuschneiden',\n addCaption: 'Beschriftung hinzufügen / bearbeiten',\n deleteImage: 'Bild löschen',\n },\n code: {\n ariaLabel: 'Codeblock-Aktionen',\n label: 'Code',\n syntaxLanguage: 'Syntaxsprache',\n syntaxAriaLabel: 'Syntaxsprache',\n copyCode: 'Code kopieren',\n toggleWordWrap: 'Zeilenumbruch umschalten',\n enableWordWrap: 'Zeilenumbruch aktivieren',\n disableWordWrap: 'Zeilenumbruch deaktivieren',\n convertToParagraph: 'In Absatz umwandeln',\n deleteCodeBlock: 'Codeblock löschen',\n },\n table: {\n ariaLabel: 'Tabellen-Aktionen',\n label: 'Tabelle',\n selectCells: 'Zellen auswählen',\n addRowAbove: 'Zeile oben hinzufügen',\n addRowBelow: 'Zeile unten hinzufügen',\n deleteRow: 'Zeile löschen',\n addColumnLeft: 'Spalte links hinzufügen',\n addColumnRight: 'Spalte rechts hinzufügen',\n deleteColumn: 'Spalte löschen',\n mergeCells: 'Zellen zusammenführen',\n unmergeCells: 'Zellen trennen',\n columnWidth: 'Spaltenbreite',\n rowHeight: 'Zeilenhöhe',\n tableBorderWidth: 'Tabellenrahmenbreite',\n deleteTable: 'Tabelle löschen',\n columnWidthPx: 'Spaltenbreite (px)',\n rowHeightPx: 'Zeilenhöhe (px)',\n tableBorderWidthPx: 'Tabellenrahmenbreite (px)',\n cancelBtn: 'Abbrechen',\n applyBtn: 'Anwenden',\n },\n video: {\n ariaLabel: 'Video-Aktionen',\n label: 'Video',\n floatLeft: 'Links umfließen',\n noFloat: 'Kein Umfluss',\n alignCenter: 'Zentriert',\n floatRight: 'Rechts umfließen',\n originalSize: 'Originalgröße',\n previewVideo: 'Video-Vorschau',\n exitPreview: 'Vorschau beenden',\n deleteVideo: 'Video löschen',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `Das Format „${type}\" wird in Webbrowsern nicht unterstützt. Bitte konvertieren Sie es zuerst in JPEG, PNG oder WebP.`,\n imageSize: (maxSize) =>\n `Die Bilddatei ist zu groß. Die maximal zulässige Größe beträgt ${maxSize} MB.`,\n },\n};\n","/**\n * es.js - Spanish locale\n * Deep-merged over en.js; only keys that differ from English are listed.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const es = {\n toolbar: {\n bold: 'Negrita (Ctrl+B)',\n italic: 'Cursiva (Ctrl+I)',\n underline: 'Subrayado (Ctrl+U)',\n strikethrough: 'Tachado',\n superscript: 'Superíndice',\n subscript: 'Subíndice',\n alignLeft: 'Alinear a la izquierda',\n alignCenter: 'Centrar',\n alignRight: 'Alinear a la derecha',\n alignJustify: 'Justificar',\n ul: 'Lista sin orden',\n ol: 'Lista ordenada',\n checklist: 'Lista de verificación',\n indent: 'Aumentar sangría',\n outdent: 'Reducir sangría',\n undo: 'Deshacer (Ctrl+Z)',\n redo: 'Rehacer (Ctrl+Y)',\n hr: 'Línea horizontal',\n link: 'Insertar enlace',\n image: 'Insertar imagen',\n video: 'Insertar vídeo',\n emoji: 'Insertar emoji',\n icon: 'Insertar icono FA',\n table: 'Insertar tabla',\n fontSize: 'Tamaño de fuente',\n fontSizePlaceholder: 'Tamaño',\n removeFormat: 'Eliminar formato',\n direction: 'Cambiar dirección del texto (LTR / RTL)',\n fontFamily: 'Fuente',\n paragraphStyle: 'Estilo de párrafo',\n paragraphStylePlaceholder: 'Estilo',\n lineHeight: 'Interlineado',\n lineHeightPlaceholder: '↕ Línea',\n codeview: 'Vista de código HTML',\n fullscreen: 'Pantalla completa',\n shortcuts: 'Atajos de teclado (Ctrl+Shift+/)',\n find: 'Buscar (Ctrl+F)',\n findReplace: 'Buscar y reemplazar (Ctrl+H)',\n inlineCode: 'Código en línea (Ctrl+`)',\n print: 'Imprimir',\n foreColor: 'Color del texto',\n backColor: 'Color de resaltado',\n chooseTextColor: 'Elegir color del texto',\n chooseHighlightColor: 'Elegir color de resaltado',\n customColor: 'Color personalizado',\n insertTableLabel: 'Insertar tabla',\n paragraphItems: {\n p: 'Normal',\n blockquote: 'Cita',\n pre: 'Código',\n },\n },\n\n linkDialog: {\n ariaLabel: 'Insertar enlace',\n title: 'Insertar enlace',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: 'Texto a mostrar',\n textPlaceholder: 'Texto del enlace',\n openInNewTab: 'Abrir en nueva pestaña',\n insertBtn: 'Insertar',\n cancelBtn: 'Cancelar',\n },\n\n imageDialog: {\n ariaLabel: 'Insertar imagen',\n title: 'Insertar imagen',\n imageUrl: 'URL de imagen',\n urlPlaceholder: 'https://example.com/image.png',\n altText: 'Texto alternativo',\n altPlaceholder: 'Describir la imagen',\n alignment: 'Alineación',\n alignNone: 'Ninguna',\n alignLeft: 'Izquierda',\n alignCenter: 'Centro',\n alignRight: 'Derecha',\n uploadLabel: 'O subir un archivo',\n insertBtn: 'Insertar',\n cancelBtn: 'Cancelar',\n },\n\n videoDialog: {\n ariaLabel: 'Insertar vídeo',\n title: 'Insertar vídeo',\n videoUrl: 'URL del vídeo',\n urlPlaceholder: 'YouTube, Vimeo o URL directa .mp4',\n widthLabel: 'Ancho (px)',\n widthPlaceholder: '560',\n insertBtn: 'Insertar',\n cancelBtn: 'Cancelar',\n detected: (type) => `Detectado: ${type}`,\n unknownFormat: 'Formato desconocido — se intentará incrustar el vídeo directamente',\n invalidUrl: 'URL no válida — introduzca un enlace de vídeo válido.',\n },\n\n emojiDialog: {\n ariaLabel: 'Insertar emoji',\n title: 'Insertar emoji',\n searchPlaceholder: 'Buscar emojis…',\n all: 'Todos',\n cancelBtn: 'Cancelar',\n close: 'Cerrar',\n categories: {\n smileys: 'Caritas',\n people: 'Personas',\n animals: 'Animales',\n food: 'Comida',\n travel: 'Viajes',\n objects: 'Objetos',\n symbols: 'Símbolos',\n },\n },\n\n iconDialog: {\n ariaLabel: 'Insertar icono FA',\n title: 'Insertar icono FA',\n searchPlaceholder: 'Buscar iconos…',\n all: 'Todos',\n style: 'Estilo',\n size: 'Tamaño',\n color: 'Color',\n useColor: ' Usar color',\n selectHint: 'Seleccionar un icono',\n insertBtn: 'Insertar icono FA',\n cancelBtn: 'Cancelar',\n close: 'Cerrar',\n categories: {\n popular: 'Popular',\n interface: 'Interfaz',\n navigation: 'Navegación',\n media: 'Medios',\n communication: 'Comunicación',\n files: 'Archivos',\n people: 'Personas',\n objects: 'Objetos',\n },\n },\n\n findReplace: {\n findTitle: 'Buscar',\n findReplaceTitle: 'Buscar y reemplazar',\n findPlaceholder: 'Buscar…',\n searchAriaLabel: 'Texto de búsqueda',\n caseSensitive: '\\u00a0Distinguir mayúsculas',\n prevBtn: '← Anterior',\n nextBtn: 'Siguiente →',\n replacePlaceholder: 'Reemplazar con…',\n replaceAriaLabel: 'Reemplazar con',\n replaceBtn: 'Reemplazar',\n replaceAllBtn: 'Reemplazar todo',\n close: '×',\n },\n\n shortcutsDialog: {\n title: 'Atajos de teclado',\n ariaLabel: 'Atajos de teclado',\n close: 'Cerrar',\n shortcuts: [\n {\n category: 'Formato de texto',\n items: [\n { keys: 'Ctrl + B', action: 'Negrita' },\n { keys: 'Ctrl + I', action: 'Cursiva' },\n { keys: 'Ctrl + U', action: 'Subrayado' },\n { keys: 'Ctrl + K', action: 'Insertar / editar enlace' },\n ],\n },\n {\n category: 'Historial',\n items: [\n { keys: 'Ctrl + Z', action: 'Deshacer' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Rehacer' },\n ],\n },\n {\n category: 'Selección y navegación',\n items: [\n { keys: 'Ctrl + A', action: 'Seleccionar todo' },\n { keys: 'Tab', action: 'Aumentar sangría / insertar espacios' },\n { keys: 'Shift + Tab', action: 'Reducir sangría' },\n ],\n },\n {\n category: 'Portapapeles',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Pegar como texto plano' },\n ],\n },\n {\n category: 'Buscar y reemplazar',\n items: [\n { keys: 'Ctrl + F', action: 'Buscar en el documento' },\n { keys: 'Ctrl + H', action: 'Buscar y reemplazar' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Mostrar este diálogo de atajos' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: 'Cortar',\n copy: 'Copiar',\n paste: 'Pegar',\n bold: 'Negrita',\n italic: 'Cursiva',\n underline: 'Subrayado',\n textColor: 'Color del texto',\n highlightColor: 'Color de resaltado',\n copyFormat: 'Copiar formato',\n pasteFormat: 'Pegar formato',\n removeFormat: 'Eliminar formato',\n link: 'Insertar enlace',\n image: 'Insertar imagen',\n video: 'Insertar vídeo',\n table: 'Insertar tabla',\n back: 'Atrás',\n noHighlight: 'Sin resaltado',\n customColor: 'Color personalizado',\n customColorLabel: 'Personalizado…',\n },\n\n statusbar: {\n resizeHandle: 'Redimensionar editor',\n words: (n) => `Palabras: ${n}`,\n wordsLimit: (n, max) => `Palabras: ${n}/${max}`,\n chars: (n) => `Caracteres: ${n}`,\n charsLimit: (n, max) => `Caracteres: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: 'Acciones de enlace',\n openLink: 'Abrir enlace',\n copyUrl: 'Copiar URL',\n editLink: 'Editar enlace',\n removeLink: 'Eliminar enlace',\n },\n image: {\n ariaLabel: 'Acciones de imagen',\n label: 'Imagen',\n floatLeft: 'Flotar a la izquierda',\n noFloat: 'Sin flotado',\n alignCenter: 'Centrar',\n floatRight: 'Flotar a la derecha',\n originalSize: 'Tamaño original',\n rotateLeft: 'Rotar a la izquierda',\n rotateRight: 'Rotar a la derecha',\n cropImage: 'Recortar imagen',\n addCaption: 'Añadir / editar pie de foto',\n deleteImage: 'Eliminar imagen',\n },\n code: {\n ariaLabel: 'Acciones de bloque de código',\n label: 'Código',\n syntaxLanguage: 'Lenguaje de sintaxis',\n syntaxAriaLabel: 'Lenguaje de sintaxis',\n copyCode: 'Copiar código',\n toggleWordWrap: 'Alternar ajuste de línea',\n enableWordWrap: 'Activar ajuste de línea',\n disableWordWrap: 'Desactivar ajuste de línea',\n convertToParagraph: 'Convertir en párrafo',\n deleteCodeBlock: 'Eliminar bloque de código',\n },\n table: {\n ariaLabel: 'Acciones de tabla',\n label: 'Tabla',\n selectCells: 'Seleccionar celdas',\n addRowAbove: 'Añadir fila encima',\n addRowBelow: 'Añadir fila debajo',\n deleteRow: 'Eliminar fila',\n addColumnLeft: 'Añadir columna a la izquierda',\n addColumnRight: 'Añadir columna a la derecha',\n deleteColumn: 'Eliminar columna',\n mergeCells: 'Combinar celdas',\n unmergeCells: 'Separar celdas',\n columnWidth: 'Ancho de columna',\n rowHeight: 'Alto de fila',\n tableBorderWidth: 'Grosor del borde de la tabla',\n deleteTable: 'Eliminar tabla',\n columnWidthPx: 'Ancho de columna (px)',\n rowHeightPx: 'Alto de fila (px)',\n tableBorderWidthPx: 'Grosor del borde (px)',\n cancelBtn: 'Cancelar',\n applyBtn: 'Aplicar',\n },\n video: {\n ariaLabel: 'Acciones de vídeo',\n label: 'Vídeo',\n floatLeft: 'Flotar a la izquierda',\n noFloat: 'Sin flotado',\n alignCenter: 'Centrar',\n floatRight: 'Flotar a la derecha',\n originalSize: 'Tamaño original',\n previewVideo: 'Vista previa de vídeo',\n exitPreview: 'Salir de la vista previa',\n deleteVideo: 'Eliminar vídeo',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `El formato \"${type}\" no es compatible con los navegadores web. Por favor, conviértalo primero a JPEG, PNG o WebP.`,\n imageSize: (maxSize) =>\n `El archivo de imagen es demasiado grande. El tamaño máximo permitido es ${maxSize} MB.`,\n },\n};\n","/**\n * ko.js - Korean locale\n * Deep-merged over en.js; only keys that differ from English are listed.\n */\n\n/** @type {Partial<import('../../../types/index.js').AsnLocale>} */\nexport const ko = {\n toolbar: {\n bold: '굵게 (Ctrl+B)',\n italic: '기울임꼴 (Ctrl+I)',\n underline: '밑줄 (Ctrl+U)',\n strikethrough: '취소선',\n superscript: '위 첨자',\n subscript: '아래 첨자',\n alignLeft: '왼쪽 정렬',\n alignCenter: '가운데 정렬',\n alignRight: '오른쪽 정렬',\n alignJustify: '양쪽 정렬',\n ul: '순서 없는 목록',\n ol: '순서 있는 목록',\n checklist: '체크리스트',\n indent: '들여쓰기',\n outdent: '내어쓰기',\n undo: '실행 취소 (Ctrl+Z)',\n redo: '다시 실행 (Ctrl+Y)',\n hr: '수평선',\n link: '링크 삽입',\n image: '이미지 삽입',\n video: '동영상 삽입',\n emoji: '이모지 삽입',\n icon: 'FA 아이콘 삽입',\n table: '표 삽입',\n fontSize: '글꼴 크기',\n fontSizePlaceholder: '크기',\n removeFormat: '서식 제거',\n direction: '텍스트 방향 전환 (LTR / RTL)',\n fontFamily: '글꼴',\n paragraphStyle: '단락 스타일',\n paragraphStylePlaceholder: '스타일',\n lineHeight: '줄 간격',\n lineHeightPlaceholder: '↕ 줄',\n codeview: 'HTML 코드 보기',\n fullscreen: '전체 화면',\n shortcuts: '키보드 단축키 (Ctrl+Shift+/)',\n find: '찾기 (Ctrl+F)',\n findReplace: '찾기 및 바꾸기 (Ctrl+H)',\n inlineCode: '인라인 코드 (Ctrl+`)',\n print: '인쇄',\n foreColor: '글자 색',\n backColor: '강조 색',\n chooseTextColor: '글자 색 선택',\n chooseHighlightColor: '강조 색 선택',\n customColor: '사용자 지정 색',\n insertTableLabel: '표 삽입',\n paragraphItems: {\n p: '기본',\n blockquote: '인용',\n pre: '코드',\n },\n },\n\n linkDialog: {\n ariaLabel: '링크 삽입',\n title: '링크 삽입',\n url: 'URL',\n urlPlaceholder: 'https://',\n displayText: '표시 텍스트',\n textPlaceholder: '링크 텍스트',\n openInNewTab: '새 탭에서 열기',\n insertBtn: '삽입',\n cancelBtn: '취소',\n },\n\n imageDialog: {\n ariaLabel: '이미지 삽입',\n title: '이미지 삽입',\n imageUrl: '이미지 URL',\n urlPlaceholder: 'https://example.com/image.png',\n altText: '대체 텍스트',\n altPlaceholder: '이미지 설명',\n alignment: '정렬',\n alignNone: '없음',\n alignLeft: '왼쪽',\n alignCenter: '가운데',\n alignRight: '오른쪽',\n uploadLabel: '또는 파일 업로드',\n insertBtn: '삽입',\n cancelBtn: '취소',\n },\n\n videoDialog: {\n ariaLabel: '동영상 삽입',\n title: '동영상 삽입',\n videoUrl: '동영상 URL',\n urlPlaceholder: 'YouTube, Vimeo 또는 직접 .mp4 URL',\n widthLabel: '너비 (px)',\n widthPlaceholder: '560',\n insertBtn: '삽입',\n cancelBtn: '취소',\n detected: (type) => `감지됨: ${type}`,\n unknownFormat: '알 수 없는 형식 — 직접 동영상 임베드를 시도합니다',\n invalidUrl: '유효하지 않은 URL — 올바른 동영상 링크를 입력하세요.',\n },\n\n emojiDialog: {\n ariaLabel: '이모지 삽입',\n title: '이모지 삽입',\n searchPlaceholder: '이모지 검색…',\n all: '전체',\n cancelBtn: '취소',\n close: '닫기',\n categories: {\n smileys: '스마일',\n people: '사람',\n animals: '동물',\n food: '음식',\n travel: '여행',\n objects: '사물',\n symbols: '기호',\n },\n },\n\n iconDialog: {\n ariaLabel: 'FA 아이콘 삽입',\n title: 'FA 아이콘 삽입',\n searchPlaceholder: '아이콘 검색…',\n all: '전체',\n style: '스타일',\n size: '크기',\n color: '색상',\n useColor: ' 색상 사용',\n selectHint: '아이콘을 선택하세요',\n insertBtn: 'FA 아이콘 삽입',\n cancelBtn: '취소',\n close: '닫기',\n categories: {\n popular: '인기',\n interface: '인터페이스',\n navigation: '탐색',\n media: '미디어',\n communication: '커뮤니케이션',\n files: '파일',\n people: '사람',\n objects: '사물',\n },\n },\n\n findReplace: {\n findTitle: '찾기',\n findReplaceTitle: '찾기 및 바꾸기',\n findPlaceholder: '찾기…',\n searchAriaLabel: '검색 텍스트',\n caseSensitive: '\\u00a0대소문자 구분',\n prevBtn: '← 이전',\n nextBtn: '다음 →',\n replacePlaceholder: '바꿀 내용…',\n replaceAriaLabel: '바꿀 내용',\n replaceBtn: '바꾸기',\n replaceAllBtn: '모두 바꾸기',\n close: '×',\n },\n\n shortcutsDialog: {\n title: '키보드 단축키',\n ariaLabel: '키보드 단축키',\n close: '닫기',\n shortcuts: [\n {\n category: '텍스트 서식',\n items: [\n { keys: 'Ctrl + B', action: '굵게' },\n { keys: 'Ctrl + I', action: '기울임꼴' },\n { keys: 'Ctrl + U', action: '밑줄' },\n { keys: 'Ctrl + K', action: '링크 삽입 / 편집' },\n ],\n },\n {\n category: '실행 기록',\n items: [\n { keys: 'Ctrl + Z', action: '실행 취소' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: '다시 실행' },\n ],\n },\n {\n category: '선택 및 탐색',\n items: [\n { keys: 'Ctrl + A', action: '전체 선택' },\n { keys: 'Tab', action: '목록 들여쓰기 / 공백 삽입' },\n { keys: 'Shift + Tab', action: '목록 내어쓰기' },\n ],\n },\n {\n category: '클립보드',\n items: [\n { keys: 'Ctrl + Shift + V', action: '일반 텍스트로 붙여넣기' },\n ],\n },\n {\n category: '찾기 및 바꾸기',\n items: [\n { keys: 'Ctrl + F', action: '문서에서 찾기' },\n { keys: 'Ctrl + H', action: '찾기 및 바꾸기' },\n ],\n },\n {\n category: '편집기',\n items: [\n { keys: 'Ctrl + Shift + /', action: '이 단축키 대화상자 표시' },\n ],\n },\n ],\n },\n\n contextMenu: {\n cut: '잘라내기',\n copy: '복사',\n paste: '붙여넣기',\n bold: '굵게',\n italic: '기울임꼴',\n underline: '밑줄',\n textColor: '글자 색',\n highlightColor: '강조 색',\n copyFormat: '서식 복사',\n pasteFormat: '서식 붙여넣기',\n removeFormat: '서식 제거',\n link: '링크 삽입',\n image: '이미지 삽입',\n video: '동영상 삽입',\n table: '표 삽입',\n back: '뒤로',\n noHighlight: '강조 없음',\n customColor: '사용자 지정 색',\n customColorLabel: '사용자 지정…',\n },\n\n statusbar: {\n resizeHandle: '편집기 크기 조정',\n words: (n) => `단어: ${n}`,\n wordsLimit: (n, max) => `단어: ${n}/${max}`,\n chars: (n) => `글자: ${n}`,\n charsLimit: (n, max) => `글자: ${n}/${max}`,\n },\n\n tooltips: {\n link: {\n ariaLabel: '링크 작업',\n openLink: '링크 열기',\n copyUrl: 'URL 복사',\n editLink: '링크 편집',\n removeLink: '링크 제거',\n },\n image: {\n ariaLabel: '이미지 작업',\n label: '이미지',\n floatLeft: '왼쪽 배치',\n noFloat: '배치 없음',\n alignCenter: '가운데 정렬',\n floatRight: '오른쪽 배치',\n originalSize: '원본 크기',\n rotateLeft: '왼쪽 회전',\n rotateRight: '오른쪽 회전',\n cropImage: '이미지 자르기',\n addCaption: '캡션 추가 / 편집',\n deleteImage: '이미지 삭제',\n },\n code: {\n ariaLabel: '코드 블록 작업',\n label: '코드',\n syntaxLanguage: '구문 언어',\n syntaxAriaLabel: '구문 언어',\n copyCode: '코드 복사',\n toggleWordWrap: '줄 바꿈 전환',\n enableWordWrap: '줄 바꿈 사용',\n disableWordWrap: '줄 바꿈 해제',\n convertToParagraph: '단락으로 변환',\n deleteCodeBlock: '코드 블록 삭제',\n },\n table: {\n ariaLabel: '표 작업',\n label: '표',\n selectCells: '셀 선택',\n addRowAbove: '위에 행 추가',\n addRowBelow: '아래에 행 추가',\n deleteRow: '행 삭제',\n addColumnLeft: '왼쪽에 열 추가',\n addColumnRight: '오른쪽에 열 추가',\n deleteColumn: '열 삭제',\n mergeCells: '셀 병합',\n unmergeCells: '셀 분할',\n columnWidth: '열 너비',\n rowHeight: '행 높이',\n tableBorderWidth: '표 테두리 너비',\n deleteTable: '표 삭제',\n columnWidthPx: '열 너비 (px)',\n rowHeightPx: '행 높이 (px)',\n tableBorderWidthPx: '표 테두리 너비 (px)',\n cancelBtn: '취소',\n applyBtn: '적용',\n },\n video: {\n ariaLabel: '동영상 작업',\n label: '동영상',\n floatLeft: '왼쪽 배치',\n noFloat: '배치 없음',\n alignCenter: '가운데 정렬',\n floatRight: '오른쪽 배치',\n originalSize: '원본 크기',\n previewVideo: '동영상 미리보기',\n exitPreview: '미리보기 종료',\n deleteVideo: '동영상 삭제',\n },\n },\n\n errors: {\n imageFormat: (type) =>\n `\"${type}\" 형식은 웹 브라우저에서 지원되지 않습니다. JPEG, PNG 또는 WebP로 변환해 주세요.`,\n imageSize: (maxSize) =>\n `이미지 파일이 너무 큽니다. 최대 허용 크기는 ${maxSize} MB입니다.`,\n },\n};\n","/**\n * i18n/index.js — Locale registry and resolver for autumn-note-ce.\n *\n * Usage:\n * lang: 'en' → built-in English (default)\n * lang: 'vi' → built-in Vietnamese\n * lang: 'ja' → built-in Japanese\n * lang: 'zh' → built-in Simplified Chinese\n * lang: 'fr' → built-in French\n * lang: 'de' → built-in German\n * lang: 'es' → built-in Spanish\n * lang: 'ko' → built-in Korean\n * lang: { ... } → custom locale object, deep-merged over English\n */\n\nimport { mergeDeep } from '../core/func.js';\nimport { en } from './en.js';\nimport { vi } from './vi.js';\nimport { ja } from './ja.js';\nimport { zh } from './zh.js';\nimport { fr } from './fr.js';\nimport { de } from './de.js';\nimport { es } from './es.js';\nimport { ko } from './ko.js';\n\n/**\n * All built-in locales keyed by their language code.\n * @type {Record<string, Partial<AsnLocale>>}\n */\nexport const locales = { en, vi, ja, zh, fr, de, es, ko };\n\n/**\n * Resolve a locale object from a lang option value.\n *\n * @param {string | Partial<AsnLocale> | null | undefined} lang\n * @returns {AsnLocale} A fully-populated locale (always contains every key from en.js).\n */\nexport function resolveLocale(lang) {\n // Default / English shortcut (no merge needed)\n if (!lang || lang === 'en') return en;\n\n if (typeof lang === 'string') {\n const partial = locales[lang];\n // Unknown language code → fall back to English\n if (!partial) return en;\n return mergeDeep(mergeDeep({}, en), partial);\n }\n\n if (typeof lang === 'object') {\n // Custom locale object supplied directly by the user\n return mergeDeep(mergeDeep({}, en), lang);\n }\n\n return en;\n}\n\n/**\n * @typedef {Object} AsnLocale (see types/index.d.ts for the full definition)\n */\n","/**\n * sanitise.js - Shared HTML and URL sanitisation utilities\n *\n * Single source of truth used by Editor, Clipboard, Codeview, and renderer.\n * DOM-parser based — no regex-based stripping of HTML (avoids bypass tricks).\n */\n\n/** Tags that are unconditionally removed from editor content. */\nconst PROHIBITED_TAGS = ['script', 'style', 'iframe', 'object', 'embed', 'form', 'button'];\n\n/** Attributes whose values must be sanitised as URLs. */\nconst URL_ATTRS = ['href', 'src', 'action', 'formaction'];\n\n/** Trusted hosts for iframe embeds when allowIframes is enabled. */\nconst TRUSTED_IFRAME_HOSTS = new Set([\n 'www.youtube.com',\n 'youtube.com',\n 'm.youtube.com',\n 'www.youtube-nocookie.com',\n 'youtube-nocookie.com',\n 'player.vimeo.com',\n]);\n\n/**\n * Sanitises an HTML string by removing dangerous elements and attributes.\n * Uses DOMParser so the sanitisation follows normal browser parsing rules —\n * no regex shortcuts that can be bypassed by encoding tricks.\n *\n * - Strips PROHIBITED_TAGS (script, style, iframe, object, embed, form, button)\n * - Allows input[type=\"checkbox\"] only inside ul.an-checklist li; removes all other <input>\n * - Removes all on* event-handler attributes\n * - Rejects javascript: and vbscript: URLs in URL attributes\n * - Rejects data: URIs everywhere except img[src] (base64 uploads)\n *\n * @param {string} html\n * @returns {string}\n */\nexport function sanitiseHTML(html, { allowIframes = false } = {}) {\n const doc = new DOMParser().parseFromString(`<body>${html || ''}</body>`, 'text/html');\n\n // Remove outright dangerous elements (optionally preserve iframes for video embeds)\n const tags = allowIframes ? PROHIBITED_TAGS.filter((t) => t !== 'iframe') : PROHIBITED_TAGS;\n tags.forEach((tag) => {\n doc.querySelectorAll(tag).forEach((el) => el.remove());\n });\n\n // Strip dangerous attributes from remaining elements\n doc.querySelectorAll('*').forEach((el) => {\n Array.from(el.attributes).forEach((attr) => {\n // Remove all event handlers (onclick, onload, onerror, …)\n if (attr.name.startsWith('on')) {\n el.removeAttribute(attr.name);\n return;\n }\n // Sanitise URL attributes\n if (URL_ATTRS.includes(attr.name)) {\n const val = attr.value.trim();\n // Block javascript: and vbscript: protocols\n if (/^(javascript|vbscript):/i.test(val)) {\n el.removeAttribute(attr.name);\n return;\n }\n // Allow data: URIs only on img[src] (base64 image uploads); block elsewhere\n if (/^data:/i.test(val) && !(attr.name === 'src' && el.tagName === 'IMG')) {\n el.removeAttribute(attr.name);\n }\n }\n\n // Strip iframe HTML-injection vectors and limit iframe src to trusted hosts.\n if (el.tagName === 'IFRAME') {\n if (attr.name === 'srcdoc') {\n el.removeAttribute(attr.name);\n return;\n }\n if (attr.name === 'src') {\n if (!isTrustedIframeSrc(attr.value)) {\n el.removeAttribute(attr.name);\n }\n return;\n }\n }\n });\n });\n\n // Allow only input[type=\"checkbox\"] inside ul.an-checklist li; strip everything else.\n // This preserves checklist state while blocking arbitrary <input> injection.\n doc.querySelectorAll('input').forEach((el) => {\n const inChecklist = el.closest('ul.an-checklist') !== null &&\n el.closest('li') !== null;\n if (!inChecklist || el.getAttribute('type') !== 'checkbox') {\n el.remove();\n } else {\n // Harden: keep only safe attributes on checklist checkboxes\n Array.from(el.attributes).forEach((attr) => {\n if (!['type', 'checked', 'contenteditable'].includes(attr.name)) {\n el.removeAttribute(attr.name);\n }\n });\n }\n });\n\n return doc.body.innerHTML;\n}\n\n/**\n * Returns true if iframe src points to an approved video host.\n * Relative, protocol-relative and invalid URLs are rejected.\n * @param {string} src\n * @returns {boolean}\n */\nfunction isTrustedIframeSrc(src) {\n const trimmed = (src || '').trim();\n if (!trimmed) return false;\n if (trimmed.startsWith('//') || trimmed.startsWith('/')) return false;\n try {\n const url = new URL(trimmed);\n if (url.protocol !== 'https:') return false;\n return TRUSTED_IFRAME_HOSTS.has(url.hostname.toLowerCase());\n } catch {\n return false;\n }\n}\n\n/**\n * Sanitises a URL string, rejecting dangerous protocols.\n *\n * Blocked protocols: javascript:, vbscript:\n * Optionally blocked: data: (safe to allow for img/src base64 embeds)\n *\n * @param {string} url\n * @param {{ allowData?: boolean }} [opts]\n * @returns {string|null} The original URL if safe, null if rejected.\n */\nexport function sanitiseUrl(url, { allowData = false } = {}) {\n const trimmed = (url || '').trim();\n if (/^(javascript|vbscript):/i.test(trimmed)) return null;\n if (!allowData && /^data:/i.test(trimmed)) return null;\n return url;\n}\n","/**\n * renderer.js - Builds the editor DOM structure\n * Inspired by Summernote's renderer.js\n */\n\nimport { createElement } from './core/dom.js';\nimport { sanitiseHTML } from './core/sanitise.js';\n\n/**\n * Renders the editor layout around the original element.\n *\n * Structure:\n * <div class=\"an-container\">\n * <div class=\"an-toolbar\">...</div>\n * <div class=\"an-editable\" contenteditable=\"true\">...</div>\n * <div class=\"an-statusbar\">...</div>\n * </div>\n *\n * @param {HTMLElement} targetEl - the original element to replace/wrap\n * @param {import('./settings.js').AsnOptions} options\n * @returns {{ container: HTMLElement, editable: HTMLElement }}\n */\nexport function renderLayout(targetEl, options) {\n const container = createElement('div', { class: 'an-container' });\n\n // Editable area\n const editable = createElement('div', {\n class: 'an-editable',\n contenteditable: options.readOnly ? 'false' : 'true',\n spellcheck: String(options.spellcheck !== false),\n 'aria-multiline': 'true',\n 'aria-label': 'Rich text editor',\n role: 'textbox',\n });\n\n // Restore auto-saved content when available; fall back to element content\n let initialContent = '';\n if (options.autoSave && options.autoSaveKey) {\n try { initialContent = localStorage.getItem(options.autoSaveKey) || ''; } catch (_) {}\n }\n if (!initialContent) {\n initialContent = targetEl.tagName === 'TEXTAREA'\n ? (targetEl.value || '').trim()\n : (targetEl.innerHTML || '').trim();\n }\n editable.innerHTML = sanitiseHTML(initialContent, { allowIframes: true });\n\n // Apply default font family so the editable renders in the configured font\n const defaultFont = options.defaultFontFamily || (options.fontFamilies && options.fontFamilies[0]);\n if (defaultFont) {\n editable.style.fontFamily = defaultFont;\n }\n\n // Apply default font size so the size dropdown shows the correct value on startup\n if (options.defaultFontSize) {\n editable.style.fontSize = options.defaultFontSize;\n }\n\n // Apply height options.\n // `height` sets the initial visible height (takes priority).\n // `minHeight` is the drag-resize floor — only applied when no explicit `height` is given.\n if (options.height) {\n editable.style.minHeight = `${options.height}px`;\n } else if (options.minHeight) {\n editable.style.minHeight = `${options.minHeight}px`;\n }\n if (options.maxHeight) {\n editable.style.maxHeight = `${options.maxHeight}px`;\n }\n\n container.appendChild(editable);\n\n // Apply dark theme\n if (options.theme === 'dark') {\n container.classList.add('an-theme-dark');\n }\n\n // Read-only mode\n if (options.readOnly) {\n container.classList.add('an-disabled');\n editable.querySelectorAll('ul.an-checklist input[type=\"checkbox\"]').forEach((cb) => {\n cb.setAttribute('disabled', '');\n });\n }\n\n // Text direction\n if (options.direction === 'rtl') {\n editable.setAttribute('dir', 'rtl');\n container.classList.add('an-dir-rtl');\n }\n\n // Toolbar overflow\n if (options.toolbarOverflow === 'scroll') {\n container.classList.add('an-toolbar-overflow-scroll');\n }\n\n // Configure sticky toolbar\n if (options.stickyToolbar) {\n container.classList.add('an-sticky-toolbar');\n if (options.stickyToolbarOffset) {\n container.style.setProperty('--an-sticky-top', `${options.stickyToolbarOffset}px`);\n }\n }\n\n // Custom focus ring colour\n if (options.focusColor) {\n container.style.setProperty('--an-focus-color', options.focusColor);\n }\n\n // Hide the original element; keep it in DOM for form submission\n targetEl.style.display = 'none';\n targetEl.insertAdjacentElement('afterend', container);\n\n return { container, editable };\n}\n","/**\n * History.js - Undo / redo stack for editor content\n * Inspired by Summernote's History module, rewritten without jQuery\n */\n\nexport class History {\n /**\n * @param {HTMLElement} editable - the contenteditable element\n * @param {number} [limit=100] - maximum number of undo/redo states\n */\n constructor(editable, limit = 100) {\n this.editable = editable;\n this._limit = limit;\n /** @type {Array<{html: string, range: {sc: string, so: number, ec: string, eo: number}|null}>} */\n this.stack = [];\n this.stackOffset = -1;\n this._savePoint();\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n _serialize() {\n return this.editable.innerHTML;\n }\n\n /**\n * Serializes the current selection as character offsets from the start of\n * the editable element, so it can be restored after innerHTML replacement.\n * @returns {{ start: number, end: number }|null}\n */\n _serializeSelection() {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const range = sel.getRangeAt(0);\n if (!this.editable.contains(range.startContainer)) return null;\n return {\n start: this._charOffset(range.startContainer, range.startOffset),\n end: this._charOffset(range.endContainer, range.endOffset),\n };\n }\n\n /**\n * Returns the character offset of (node, offset) from the beginning of\n * the editable's text content.\n * @param {Node} node\n * @param {number} offset\n * @returns {number}\n */\n _charOffset(node, offset) {\n let count = 0;\n const walker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);\n let cur;\n while ((cur = walker.nextNode())) {\n if (cur === node) return count + offset;\n count += cur.length;\n }\n return 0;\n }\n\n /**\n * Restores a previously serialized selection inside the editable.\n * @param {{ start: number, end: number }|null} saved\n */\n _restoreSelection(saved) {\n if (!saved) return;\n let startNode = null, startOff = 0;\n let endNode = null, endOff = 0;\n let count = 0;\n const walker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);\n let cur;\n while ((cur = walker.nextNode())) {\n const len = cur.length;\n if (!startNode && count + len >= saved.start) {\n startNode = cur;\n startOff = saved.start - count;\n }\n if (!endNode && count + len >= saved.end) {\n endNode = cur;\n endOff = saved.end - count;\n break;\n }\n count += len;\n }\n if (!startNode) {\n // Offset exceeds content (e.g. undo to a shorter state): place at end\n const lastWalker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);\n let lastNode = null;\n while ((lastNode = lastWalker.nextNode())) { startNode = lastNode; }\n startOff = startNode ? startNode.length : 0;\n endNode = startNode;\n endOff = startOff;\n }\n if (!endNode) { endNode = startNode; endOff = startOff; }\n try {\n const range = document.createRange();\n range.setStart(startNode, startOff);\n range.setEnd(endNode, endOff);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_) { /* detached node — ignore */ }\n }\n\n _savePoint() {\n // Trim future history if we're mid-stack\n if (this.stackOffset < this.stack.length - 1) {\n this.stack = this.stack.slice(0, this.stackOffset + 1);\n }\n const raw = this._serialize();\n const { html, images } = this._tokenizeImages(raw);\n this.stack.push({ html, images, sel: this._serializeSelection() });\n if (this.stack.length > this._limit) {\n this.stack.shift();\n } else {\n this.stackOffset++;\n }\n }\n\n _restore(point) {\n if (!point) return;\n this.editable.innerHTML = this._detokenizeImages(point);\n this._restoreSelection(point.sel);\n }\n\n // ---------------------------------------------------------------------------\n // Base64 tokenisation — keeps snapshot strings small so that the\n // per-keystroke `recordUndo` string comparison stays fast even when the\n // editor contains large embedded images.\n // ---------------------------------------------------------------------------\n\n /**\n * Replaces every `data:…;base64,…` occurrence in `html` with a compact\n * token `__asn_img_0__`, `__asn_img_1__`, … and returns the tokenized\n * string together with a map from token → original data URL.\n * @param {string} html\n * @returns {{ html: string, images: Object<string,string> }}\n */\n _tokenizeImages(html) {\n const images = {};\n let index = 0;\n const tokenized = html.replace(/data:[^;]+;base64,[^\"' >]*/g, (match) => {\n const token = `__asn_img_${index}__`;\n images[token] = match;\n index++;\n return token;\n });\n return { html: tokenized, images };\n }\n\n /**\n * Restores a snapshot by replacing tokens back with their data URLs.\n * @param {{ html: string, images: Object<string,string> }} point\n * @returns {string}\n */\n _detokenizeImages(point) {\n if (!point.images || Object.keys(point.images).length === 0) return point.html;\n return point.html.replace(/__asn_img_\\d+__/g, (token) => point.images[token] || token);\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Records the current editor state as a history checkpoint.\n */\n recordUndo() {\n const current = this._serialize();\n const { html: tokenized } = this._tokenizeImages(current);\n const prev = this.stack[this.stackOffset];\n if (prev && prev.html === tokenized) return; // No change\n this._savePoint();\n }\n\n /**\n * Undo to the previous state.\n */\n undo() {\n if (this.stackOffset <= 0) return;\n this.stackOffset--;\n this._restore(this.stack[this.stackOffset]);\n }\n\n /**\n * Redo to the next state.\n */\n redo() {\n if (this.stackOffset >= this.stack.length - 1) return;\n this.stackOffset++;\n this._restore(this.stack[this.stackOffset]);\n }\n\n /**\n * Resets the history stack (e.g. on editor destroy or full content replace).\n */\n reset() {\n this.stack = [];\n this.stackOffset = -1;\n this._savePoint();\n }\n\n /** @returns {boolean} */\n canUndo() {\n return this.stackOffset > 0;\n }\n\n /** @returns {boolean} */\n canRedo() {\n return this.stackOffset < this.stack.length - 1;\n }\n}\n","/**\n * Table.js - Table creation and manipulation utilities\n * Inspired by Summernote's table handling\n */\n\nimport { createElement } from '../core/dom.js';\nimport { execCommand } from './Style.js';\n\n// ---------------------------------------------------------------------------\n// Table creation\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a table element with the specified dimensions.\n * @param {number} cols\n * @param {number} rows\n * @param {{ headerRow?: boolean }} [opts]\n * @returns {HTMLTableElement}\n */\nexport function createTable(cols, rows, opts = {}) {\n const { headerRow = false } = opts;\n const table = createElement('table', { class: 'an-table' });\n\n if (headerRow && rows > 0) {\n const thead = createElement('thead');\n const tr = createElement('tr');\n for (let c = 0; c < cols; c++) {\n const th = createElement('th', {}, ['\\u00a0']);\n tr.appendChild(th);\n }\n thead.appendChild(tr);\n table.appendChild(thead);\n }\n\n const bodyRows = headerRow ? Math.max(rows - 1, 1) : rows;\n const tbody = createElement('tbody');\n table.appendChild(tbody);\n\n for (let r = 0; r < bodyRows; r++) {\n const tr = createElement('tr');\n for (let c = 0; c < cols; c++) {\n const td = createElement('td', {}, ['\\u00a0']); // \n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n return table;\n}\n\n/**\n * Inserts a table at the current cursor position.\n * @param {number} cols\n * @param {number} rows\n * @param {{ headerRow?: boolean }} [opts]\n */\nexport function insertTable(cols, rows, opts = {}) {\n const table = createTable(cols, rows, opts);\n execCommand('insertHTML', table.outerHTML);\n}\n","/**\n * key.js - Keyboard key code constants\n * Inspired by Summernote's key.js\n */\n\nexport const key = {\n BACKSPACE: 'Backspace',\n TAB: 'Tab',\n ENTER: 'Enter',\n ESCAPE: 'Escape',\n SPACE: ' ',\n PAGE_UP: 'PageUp',\n PAGE_DOWN: 'PageDown',\n END: 'End',\n HOME: 'Home',\n LEFT: 'ArrowLeft',\n UP: 'ArrowUp',\n RIGHT: 'ArrowRight',\n DOWN: 'ArrowDown',\n DELETE: 'Delete',\n // Numbers\n NUM0: '0',\n NUM1: '1',\n NUM2: '2',\n NUM3: '3',\n NUM4: '4',\n NUM5: '5',\n NUM6: '6',\n NUM7: '7',\n NUM8: '8',\n // Letters\n B: 'b',\n E: 'e',\n I: 'i',\n J: 'j',\n K: 'k',\n L: 'l',\n R: 'r',\n S: 's',\n U: 'u',\n V: 'v',\n Y: 'y',\n Z: 'z',\n SLASH: '/',\n PERIOD: '.',\n};\n\n/**\n * Returns true if the event matches the given key\n * @param {KeyboardEvent} event\n * @param {string} keyName - one of key.*\n * @returns {boolean}\n */\nexport function isKey(event, keyName) {\n return event.key === keyName || event.key === keyName.toUpperCase();\n}\n\n/**\n * Returns true if the event is a modifier key press (Ctrl/Cmd + key)\n * @param {KeyboardEvent} event\n * @param {string} keyName\n * @returns {boolean}\n */\nexport function isModifier(event, keyName) {\n return (event.ctrlKey || event.metaKey) && isKey(event, keyName);\n}\n","/**\n * Typing.js - Keyboard typing event handling (Enter, Tab, Backspace behaviour)\n * Inspired by Summernote's Typing module\n */\n\nimport { key, isKey } from '../core/key.js';\nimport { closestPara, isLi } from '../core/dom.js';\nimport { execCommand, outdent } from './Style.js';\nimport { currentRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// Module-level predicates — defined once, not re-created on every keypress.\n// Previously these were arrow functions inside handleKeydown() which fires\n// at ~120+ events/sec during normal typing.\n// ---------------------------------------------------------------------------\nconst _FA_PATTERN = /\\bfa-/;\nconst isFAIcon = (n) => !!(n && n.nodeName === 'I' && _FA_PATTERN.test(n.className || ''));\nconst isZwsAnchor = (n) => !!(n && n.nodeType === Node.TEXT_NODE && (n.textContent === '\\u200B' || n.textContent === ''));\n\n/**\n * Handles special keydown behaviour inside the editor.\n * @param {KeyboardEvent} event\n * @param {HTMLElement} editable\n * @param {object} options - editor options\n * @returns {boolean} true if the event was consumed\n */\nexport function handleKeydown(event, editable, options = {}) {\n const moveCaret = (setFn) => {\n const sel = window.getSelection();\n if (!sel) return false;\n const nr = document.createRange();\n setFn(nr);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n };\n\n // -------------------------------------------------------------------------\n // Backspace key — one-press deletion of a preceding FA icon (<i> element)\n // -------------------------------------------------------------------------\n if (isKey(event, key.BACKSPACE)) {\n const sel = window.getSelection();\n if (sel && sel.rangeCount > 0) {\n const r = sel.getRangeAt(0);\n if (r.collapsed && r.startContainer.nodeType === Node.TEXT_NODE) {\n const textNode = r.startContainer;\n // Case A: cursor at offset 0, preceding sibling is an FA icon\n if (r.startOffset === 0 && isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n textNode.previousSibling.remove();\n return true;\n }\n\n // Case B: cursor at offset 1 of a ZWS-only text node whose preceding\n // sibling is an FA icon. The ZWS is the invisible caret anchor inserted\n // by IconDialog; treat the whole Backspace as \"delete icon + its anchor\".\n if (r.startOffset === 1 && textNode.textContent === '\\u200B' &&\n isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n const parent = textNode.parentNode;\n const icon = textNode.previousSibling;\n const prevNode = icon.previousSibling; // node before the icon (e.g. ZWS of prior icon)\n icon.remove();\n textNode.remove();\n // Explicitly restore the cursor to the node preceding the deleted icon.\n // Without this, the browser collapses the selection to the parent element\n // (not a text node), causing the next Backspace to miss Cases A/B and\n // requiring an extra keypress when two icons are adjacent.\n const nr = document.createRange();\n if (prevNode && prevNode.nodeType === Node.TEXT_NODE) {\n nr.setStart(prevNode, prevNode.textContent.length);\n } else if (prevNode) {\n nr.setStartAfter(prevNode);\n } else if (parent) {\n nr.setStart(parent, 0);\n }\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n }\n }\n return false;\n }\n\n // -------------------------------------------------------------------------\n // ArrowLeft / ArrowRight — one-press navigation across FA icon nodes\n // -------------------------------------------------------------------------\n if (isKey(event, key.LEFT) || isKey(event, key.RIGHT)) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return false;\n\n const r = sel.getRangeAt(0);\n if (!r.collapsed) return false;\n\n const sc = r.startContainer;\n const movingLeft = isKey(event, key.LEFT);\n\n if (sc.nodeType === Node.TEXT_NODE) {\n const textNode = sc;\n\n if (movingLeft &&\n r.startOffset === 1 &&\n textNode.textContent === '\\u200B' &&\n isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(textNode.previousSibling));\n }\n\n if (movingLeft && r.startOffset === 0 && isFAIcon(textNode.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(textNode.previousSibling));\n }\n\n if (movingLeft &&\n r.startOffset === 0 &&\n isZwsAnchor(textNode.previousSibling) &&\n isFAIcon(textNode.previousSibling.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(textNode.previousSibling.previousSibling));\n }\n\n if (!movingLeft &&\n r.startOffset === textNode.textContent.length &&\n isFAIcon(textNode.nextSibling)) {\n const icon = textNode.nextSibling;\n const after = icon.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(icon));\n }\n\n if (!movingLeft &&\n r.startOffset === textNode.textContent.length &&\n isZwsAnchor(textNode.nextSibling) &&\n isFAIcon(textNode.nextSibling.nextSibling)) {\n const icon = textNode.nextSibling.nextSibling;\n const after = icon.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(icon));\n }\n }\n\n if (sc.nodeType === Node.ELEMENT_NODE) {\n const el = sc;\n if (movingLeft && r.startOffset > 0) {\n const prev = el.childNodes[r.startOffset - 1];\n if (isFAIcon(prev)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(prev));\n }\n if (isZwsAnchor(prev) && isFAIcon(prev.previousSibling)) {\n event.preventDefault();\n return moveCaret((nr) => nr.setStartBefore(prev.previousSibling));\n }\n }\n if (!movingLeft && r.startOffset < el.childNodes.length) {\n const next = el.childNodes[r.startOffset];\n if (isFAIcon(next)) {\n const after = next.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(next));\n }\n if (isZwsAnchor(next) && isFAIcon(next.nextSibling)) {\n const icon = next.nextSibling;\n const after = icon.nextSibling;\n event.preventDefault();\n if (after && after.nodeType === Node.TEXT_NODE) {\n const offset = ((after.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));\n }\n return moveCaret((nr) => nr.setStartAfter(icon));\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Tab key — indent / outdent list items, or insert soft tab in code blocks\n // -------------------------------------------------------------------------\n if (isKey(event, key.TAB)) {\n const range = currentRange(editable);\n if (!range) return false;\n\n const para = closestPara(range.sc, editable);\n if (para && isLi(para)) {\n event.preventDefault();\n if (event.shiftKey) {\n outdent();\n } else {\n execCommand('indent');\n }\n return true;\n }\n\n // In a pre/code block, insert spaces\n if (para && para.nodeName.toUpperCase() === 'PRE') {\n if (event.shiftKey) return false;\n event.preventDefault();\n execCommand('insertText', ' ');\n return true;\n }\n\n // Default: insert * tabSize\n if (options.tabSize) {\n if (event.shiftKey) return false;\n event.preventDefault();\n execCommand('insertText', ' '.repeat(options.tabSize));\n return true;\n }\n }\n\n // -------------------------------------------------------------------------\n // Shift+Enter — insert <br> instead of opening a new block element\n // -------------------------------------------------------------------------\n if (isKey(event, key.ENTER) && event.shiftKey) {\n event.preventDefault();\n execCommand('insertLineBreak');\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Enter key — keep consistent paragraph insertion\n // -------------------------------------------------------------------------\n if (isKey(event, key.ENTER) && !event.shiftKey) {\n const range = currentRange(editable);\n if (!range) return false;\n\n // Hoist sc/el once so all guards below can reuse them.\n const sc = range.sc;\n const el = sc.nodeType === 3 ? sc.parentElement : sc;\n\n // Guard: if the cursor is inside a <i> FA icon element (zero text children,\n // rendered entirely by CSS ::before), pressing Enter would split the block\n // and leave an orphan <i> in the new paragraph — visually an \"auto-created\n // icon\". Push the cursor to just after the <i> first, then fall through so\n // the browser fires its default Enter at a safe text boundary.\n if (el && el.nodeName === 'I' && /\\bfa-/.test(el.className || '')) {\n const nr = document.createRange();\n nr.setStartAfter(el);\n nr.collapse(true);\n const selI = window.getSelection();\n if (selI) { selI.removeAllRanges(); selI.addRange(nr); }\n return false; // cursor is now outside <i> — let browser default handle Enter\n }\n\n // Video wrapper — Enter should create a new paragraph after the wrapper,\n // not split the wrapper's container and produce an empty video clone.\n const videoWrapper = el && el.closest && el.closest('.an-video-wrapper');\n if (videoWrapper) {\n event.preventDefault();\n const p = document.createElement('p');\n p.innerHTML = '\\u00a0';\n videoWrapper.parentNode.insertBefore(p, videoWrapper.nextSibling);\n const nr = document.createRange();\n nr.setStart(p, 0);\n nr.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n\n // Checklist — Enter creates new item; empty item exits the list\n const checkLi = el && el.closest && el.closest('.an-checklist li');\n if (checkLi) {\n event.preventDefault();\n const ul = checkLi.closest('.an-checklist');\n const sel = window.getSelection();\n let nativeRange = sel.getRangeAt(0);\n\n // Helper: get trimmed text content of a li, excluding the checkbox INPUT.\n // Strip both \\u00a0 (placeholder nbsp) and \\u200B (ZWS cursor anchors).\n const liText = (li) =>\n Array.from(li.childNodes)\n .filter((n) => !(n.nodeType === 1 && n.tagName === 'INPUT'))\n .map((n) => n.textContent).join('').replace(/[\\u00a0\\u200B]/g, ' ').trim();\n\n // 1. Check if the ENTIRE item is empty BEFORE any DOM mutation.\n // (Do NOT check only the \"before-cursor\" part — that check incorrectly\n // exits the list when cursor is at the start of a non-empty item.)\n if (!liText(checkLi)) {\n // Empty item — exit checklist, insert <p> after list\n const p = document.createElement('p');\n p.innerHTML = '\\u00a0';\n ul.parentNode.insertBefore(p, ul.nextSibling);\n checkLi.remove();\n if (ul.children.length === 0) ul.remove();\n const nr = document.createRange();\n nr.setStart(p.firstChild, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n\n // 2. If selection is not collapsed, delete the selected content first —\n // mirrors browser-default Enter behaviour (delete selection, then split).\n if (!nativeRange.collapsed) {\n nativeRange.deleteContents();\n // nativeRange is now collapsed at the deletion point; re-read it\n nativeRange = sel.getRangeAt(0);\n }\n\n // 3. Extract everything from cursor to end of li into afterFrag.\n // Use startContainer/startOffset (cursor position after potential delete),\n // NOT endContainer/endOffset which is wrong for non-collapsed ranges.\n const afterRange = document.createRange();\n afterRange.setStart(nativeRange.startContainer, nativeRange.startOffset);\n afterRange.setEnd(checkLi, checkLi.childNodes.length);\n const afterFrag = afterRange.extractContents();\n\n // 4. Build the new checklist item with the extracted \"after\" content.\n const newLi = document.createElement('li');\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.setAttribute('contenteditable', 'false');\n newLi.appendChild(cb);\n\n // Append extracted \"after\" content (if any) then insert the new item.\n if (afterFrag.textContent.replace(/[\\u00a0\\u200B]/g, '').length > 0) {\n newLi.appendChild(afterFrag);\n }\n\n // Always ensure a text node exists so the cursor has a text-level\n // anchor. Use \\u200B (zero-width space) instead of an empty string:\n // Chrome does not reliably honour a Selection in an empty text node and\n // may normalise it to element-level, placing the caret before the\n // absolutely-positioned checkbox. \\u200B is stripped by getHTML().\n let cursorNode = newLi.childNodes[1]; // first child after checkbox\n if (!cursorNode || cursorNode.nodeType !== Node.TEXT_NODE) {\n cursorNode = document.createTextNode('\\u200B');\n newLi.appendChild(cursorNode);\n }\n checkLi.insertAdjacentElement('afterend', newLi);\n\n const nr = document.createRange();\n nr.setStart(cursorNode, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n return true;\n }\n\n const para = closestPara(range.sc, editable);\n\n // Pressing Enter at the end of a blockquote should exit it\n if (para && para.nodeName.toUpperCase() === 'BLOCKQUOTE') {\n const native = range.toNativeRange();\n native.setEnd(para, para.childNodes.length);\n if (native.toString() === '' && range.isCollapsed()) {\n event.preventDefault();\n execCommand('formatBlock', '<p>');\n return true;\n }\n }\n }\n\n return false;\n}\n","/**\n * markdown.js - Lightweight Markdown → HTML converter for paste handling.\n *\n * Handles: headings H1–H6, bold/italic/strikethrough/inline-code, fenced code\n * blocks (with language), blockquotes, unordered/ordered lists, horizontal\n * rules, links, images, and plain paragraphs.\n *\n * The HTML output MUST be passed through sanitiseHTML() before insertion.\n */\n\n/**\n * Converts an HTML string to Markdown.\n * Handles: headings, paragraphs, bold/italic/del/code, links, images,\n * unordered/ordered lists, blockquote, pre/code blocks, tables, hr.\n * @param {string} html\n * @returns {string}\n */\nexport function htmlToMarkdown(html) {\n const doc = new DOMParser().parseFromString(`<body>${html || ''}</body>`, 'text/html');\n return _domToMd(doc.body).replace(/\\n{3,}/g, '\\n\\n').trim();\n}\n\nfunction _domToMd(node) {\n if (node.nodeType === 3) {\n return node.textContent.replace(/\\s+/g, ' ');\n }\n if (node.nodeType !== 1) return '';\n\n const tag = node.nodeName.toLowerCase();\n const inner = () => Array.from(node.childNodes).map(_domToMd).join('');\n\n switch (tag) {\n case 'p':\n case 'div': return `\\n\\n${inner()}\\n\\n`;\n case 'br': return ' \\n';\n case 'h1': return `\\n\\n# ${inner()}\\n\\n`;\n case 'h2': return `\\n\\n## ${inner()}\\n\\n`;\n case 'h3': return `\\n\\n### ${inner()}\\n\\n`;\n case 'h4': return `\\n\\n#### ${inner()}\\n\\n`;\n case 'h5': return `\\n\\n##### ${inner()}\\n\\n`;\n case 'h6': return `\\n\\n###### ${inner()}\\n\\n`;\n case 'strong':\n case 'b': return `**${inner()}**`;\n case 'em':\n case 'i': return `*${inner()}*`;\n case 'del':\n case 's':\n case 'strike': return `~~${inner()}~~`;\n case 'sup': return `^${inner()}`;\n case 'sub': return `~${inner()}`;\n case 'code': {\n // Inside <pre> we emit raw text; outside we wrap in backticks\n if (node.closest('pre')) return inner();\n return `\\`${inner()}\\``;\n }\n case 'pre': {\n const codeEl = node.querySelector('code');\n const langMatch = ((codeEl && codeEl.className) || '').match(/language-(\\S+)/);\n const lang = langMatch ? langMatch[1] : '';\n const content = (codeEl || node).textContent || '';\n return `\\n\\n\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n\\n`;\n }\n case 'blockquote': {\n const lines = inner().trim().split('\\n');\n return `\\n\\n${lines.map((l) => `> ${l}`).join('\\n')}\\n\\n`;\n }\n case 'a': {\n const href = node.getAttribute('href') || '';\n return `[${inner()}](${href})`;\n }\n case 'img': {\n const src = node.getAttribute('src') || '';\n const alt = node.getAttribute('alt') || '';\n return ``;\n }\n case 'ul': {\n const items = Array.from(node.querySelectorAll(':scope > li'));\n if (!items.length) return inner();\n return `\\n\\n${items.map((li) => `- ${_domToMd(li).trim()}`).join('\\n')}\\n\\n`;\n }\n case 'ol': {\n const items = Array.from(node.querySelectorAll(':scope > li'));\n if (!items.length) return inner();\n return `\\n\\n${items.map((li, i) => `${i + 1}. ${_domToMd(li).trim()}`).join('\\n')}\\n\\n`;\n }\n case 'li': return inner();\n case 'hr': return '\\n\\n---\\n\\n';\n case 'table': {\n const rows = Array.from(node.querySelectorAll('tr'));\n if (!rows.length) return inner();\n const cellTexts = rows.map((tr) =>\n Array.from(tr.querySelectorAll('th, td')).map((c) => c.textContent.trim().replace(/\\|/g, '\\\\|')),\n );\n const cols = Math.max(...cellTexts.map((r) => r.length));\n const padRow = (row) => { const r = [...row]; while (r.length < cols) r.push(''); return r; };\n let md = '\\n\\n';\n md += `| ${padRow(cellTexts[0]).join(' | ')} |\\n`;\n md += `| ${Array(cols).fill('---').join(' | ')} |\\n`;\n for (let r = 1; r < cellTexts.length; r++) {\n md += `| ${padRow(cellTexts[r]).join(' | ')} |\\n`;\n }\n return md + '\\n';\n }\n default: return inner();\n }\n}\n\n/**\n * Returns true if the text contains recognisable Markdown patterns.\n * @param {string} text\n * @returns {boolean}\n */\nexport function isMarkdown(text) {\n return /^#{1,6} \\S|^\\s*[-*+] \\S|^\\s*\\d+\\. \\S|^> \\S|\\*{2}.+?\\*{2}|^```/m.test(text);\n}\n\n/**\n * Converts a Markdown string to an HTML string.\n * @param {string} text\n * @returns {string}\n */\nexport function markdownToHTML(text) {\n const lines = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n').split('\\n');\n const out = [];\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i];\n\n // ---- Fenced code block ``` lang ... ``` -----------------------------------\n const fenceMatch = line.match(/^```(\\S*)$/);\n if (fenceMatch) {\n const lang = fenceMatch[1];\n const codeLines = [];\n i++;\n while (i < lines.length && !lines[i].startsWith('```')) {\n codeLines.push(_esc(lines[i]));\n i++;\n }\n const langAttr = lang ? ` class=\"language-${_escAttr(lang)}\"` : '';\n out.push(`<pre><code${langAttr}>${codeLines.join('\\n')}</code></pre>`);\n i++; // skip closing ```\n continue;\n }\n\n // ---- Horizontal rule --- / *** / _________________________________________\n if (/^(-{3,}|\\*{3,}|_{3,})\\s*$/.test(line)) {\n out.push('<hr>');\n i++;\n continue;\n }\n\n // ---- ATX Headings # – ###### -------------------------------------------\n const hMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (hMatch) {\n const level = hMatch[1].length;\n out.push(`<h${level}>${_inline(hMatch[2])}</h${level}>`);\n i++;\n continue;\n }\n\n // ---- Blockquote > text --------------------------------------------------\n if (line.startsWith('> ')) {\n const bqLines = [];\n while (i < lines.length && lines[i].startsWith('> ')) {\n bqLines.push(lines[i].slice(2));\n i++;\n }\n out.push(`<blockquote>${bqLines.map(_inline).join('<br>')}</blockquote>`);\n continue;\n }\n\n // ---- Unordered list - / * / + item ------------------------------------\n if (/^[-*+] /.test(line)) {\n const items = [];\n while (i < lines.length && /^[-*+] /.test(lines[i])) {\n items.push(`<li>${_inline(lines[i].slice(2))}</li>`);\n i++;\n }\n out.push(`<ul>${items.join('')}</ul>`);\n continue;\n }\n\n // ---- Ordered list 1. item ----------------------------------------------\n if (/^\\d+\\. /.test(line)) {\n const items = [];\n while (i < lines.length && /^\\d+\\. /.test(lines[i])) {\n items.push(`<li>${_inline(lines[i].replace(/^\\d+\\. /, ''))}</li>`);\n i++;\n }\n out.push(`<ol>${items.join('')}</ol>`);\n continue;\n }\n\n // ---- Blank line ----------------------------------------------------------\n if (line.trim() === '') {\n i++;\n continue;\n }\n\n // ---- GFM Table | col | col | -------------------------------------------\n // A table starts with a pipe-prefixed or pipe-containing line followed by\n // a separator row (| --- | --- |). We detect and collect all rows.\n if (/^\\|.+\\|/.test(line) && i + 1 < lines.length && /^\\|[\\s|:-]+\\|/.test(lines[i + 1])) {\n const headerCells = _parseTableRow(line);\n i += 2; // skip header + separator\n const bodyRows = [];\n while (i < lines.length && /^\\|.+\\|/.test(lines[i])) {\n bodyRows.push(_parseTableRow(lines[i]));\n i++;\n }\n const thead = `<thead><tr>${headerCells.map((c) => `<th>${_inline(c)}</th>`).join('')}</tr></thead>`;\n const tbody = bodyRows.length\n ? `<tbody>${bodyRows.map((row) => `<tr>${row.map((c) => `<td>${_inline(c)}</td>`).join('')}</tr>`).join('')}</tbody>`\n : '';\n out.push(`<table>${thead}${tbody}</table>`);\n continue;\n }\n\n // ---- Paragraph: collect consecutive non-block lines ---------------------\n const paraLines = [];\n while (\n i < lines.length &&\n lines[i].trim() !== '' &&\n !/^(#{1,6} |> |[-*+] |\\d+\\. |```|---\\s*$|\\*{3}\\s*$|_{3}\\s*$)/.test(lines[i]) &&\n !/^\\|.+\\|/.test(lines[i])\n ) {\n paraLines.push(lines[i]);\n i++;\n }\n if (paraLines.length) {\n out.push(`<p>${_inline(paraLines.join(' '))}</p>`);\n }\n }\n\n return out.join('');\n}\n\n// ---------------------------------------------------------------------------\n// Inline formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Splits a GFM table row string into trimmed cell strings.\n * '| a | b | c |' → ['a', 'b', 'c']\n * @param {string} row\n * @returns {string[]}\n */\nfunction _parseTableRow(row) {\n return row\n .replace(/^\\|/, '')\n .replace(/\\|$/, '')\n .split('|')\n .map((c) => c.trim());\n}\n\nfunction _inline(text) {\n // Images before links (they share [] syntax)\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, (_, alt, src) =>\n `<img src=\"${_escAttr(src)}\" alt=\"${_escAttr(alt)}\" class=\"an-image\">`);\n // Links\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, label, href) =>\n `<a href=\"${_escAttr(href)}\">${_esc(label)}</a>`);\n // Bold + italic ***text***\n text = text.replace(/\\*{3}(.+?)\\*{3}/g, (_, c) => `<strong><em>${_esc(c)}</em></strong>`);\n text = text.replace(/_{3}(.+?)_{3}/g, (_, c) => `<strong><em>${_esc(c)}</em></strong>`);\n // Bold **text**\n text = text.replace(/\\*{2}(.+?)\\*{2}/g, (_, c) => `<strong>${_esc(c)}</strong>`);\n text = text.replace(/_{2}(.+?)_{2}/g, (_, c) => `<strong>${_esc(c)}</strong>`);\n // Italic *text* _text_\n text = text.replace(/\\*([^*\\n]+?)\\*/g, (_, c) => `<em>${_esc(c)}</em>`);\n text = text.replace(/_([^_\\n]+?)_/g, (_, c) => `<em>${_esc(c)}</em>`);\n // Strikethrough ~~text~~\n text = text.replace(/~~(.+?)~~/g, (_, c) => `<del>${_esc(c)}</del>`);\n // Inline code `code`\n text = text.replace(/`([^`]+)`/g, (_, c) => `<code>${_esc(c)}</code>`);\n return text;\n}\n\nfunction _esc(v) {\n return String(v)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nfunction _escAttr(v) {\n return String(v)\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n","/**\n * Editor.js - Core editing command module\n * Wraps all execCommand calls, undo/redo, and fires events via the context.\n * Inspired by Summernote's Editor module.\n */\n\nimport { History } from '../editing/History.js';\nimport * as Style from '../editing/Style.js';\nimport { insertTable } from '../editing/Table.js';\nimport { isModifier } from '../core/key.js';\nimport { handleKeydown } from '../editing/Typing.js';\nimport { on } from '../core/dom.js';\nimport { sanitiseHTML, sanitiseUrl } from '../core/sanitise.js';\nimport { markdownToHTML, htmlToMarkdown } from '../core/markdown.js';\n\nexport class Editor {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {History|null} */\n this._history = null;\n this._disposers = [];\n /** @type {number|null} Timer handle for debounced undo snapshot */\n this._snapshotTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n const editable = this.context.layoutInfo.editable;\n this._history = new History(editable, this.options.historyLimit || 100);\n this._bindEvents(editable);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n this._history = null;\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Event binding\n // ---------------------------------------------------------------------------\n\n _bindEvents(editable) {\n // Keyboard shortcuts\n const onKeydown = (event) => this._onKeydown(event);\n // Catch ALL content mutations: typing, IME, spellcheck, voice, drag-drop text.\n const onInput = () => this.afterCommand();\n // Hard-enforce maxChars / maxWords before content is mutated\n const onBeforeInput = (event) => this._enforceLimit(event);\n // Refresh toolbar on selection change, scoped to this editor\n const onSelChange = () => {\n if (!this.context._alive) return;\n const sel = window.getSelection();\n if (sel && sel.rangeCount > 0 && editable.contains(sel.anchorNode)) {\n this.context.invoke('toolbar.refresh');\n if (typeof this.options.onSelectionChange === 'function') {\n this.options.onSelectionChange(this.context);\n }\n }\n };\n\n // Checklist checkboxes are contenteditable=false so native clicks work;\n // hook afterCommand so the checked state is preserved in undo history.\n const onCheckboxClick = (e) => {\n if (e.target.type === 'checkbox' && e.target.closest('.an-checklist')) {\n this.afterCommand();\n }\n };\n\n // Guard: when cursor lands at the <li> element node of a checklist item\n // (before the checkbox), nudge it to the correct text position.\n //\n // mouseup: use caretRangeFromPoint / caretPositionFromPoint so the cursor\n // lands WHERE the user actually clicked (middle, end of text…).\n // keyup : arrow-key navigation may land at <li>[0]; move to start-of-text.\n const fixChecklistCursor = (event) => {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const r = sel.getRangeAt(0);\n if (!r.collapsed) return;\n const sc = r.startContainer;\n\n // Only act when cursor is at the <li> element node itself (not inside\n // a text node — the browser already placed it correctly in that case).\n if (sc.nodeType !== Node.ELEMENT_NODE) return;\n const li = sc.matches && sc.matches('.an-checklist li') ? sc : null;\n if (!li) return;\n const cb = li.querySelector('input[type=\"checkbox\"]');\n if (!cb) return;\n\n // For mouse events: ask the browser where the pointer landed so the\n // cursor respects the actual click position inside the text.\n if (event && event.type === 'mouseup') {\n let caret = null;\n if (document.caretRangeFromPoint) {\n caret = document.caretRangeFromPoint(event.clientX, event.clientY);\n } else if (document.caretPositionFromPoint) {\n const cp = document.caretPositionFromPoint(event.clientX, event.clientY);\n if (cp) {\n caret = document.createRange();\n caret.setStart(cp.offsetNode, cp.offset);\n }\n }\n // If the caret from point landed inside a text node of this li, use it\n if (caret && editable.contains(caret.startContainer) &&\n caret.startContainer !== li) {\n caret.collapse(true);\n sel.removeAllRanges();\n sel.addRange(caret);\n return;\n }\n }\n\n // Fallback (keyboard nav, or caretRangeFromPoint not available / landed\n // at li again): prefer the first text node after the checkbox so the\n // cursor renders at the padding-left edge (after the visual checkbox)\n // rather than at element-level where the browser may place it at x=0.\n const nr = document.createRange();\n let anchorNode = null;\n for (const child of li.childNodes) {\n if (child !== cb && child.nodeType === Node.TEXT_NODE) {\n anchorNode = child;\n break;\n }\n }\n if (anchorNode) {\n nr.setStart(anchorNode, 0);\n } else {\n nr.setStartAfter(cb);\n }\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n };\n\n const isReadOnly = () => this.context.layoutInfo.container.classList.contains('an-disabled');\n\n this._disposers.push(\n on(editable, 'keydown', onKeydown),\n on(editable, 'beforeinput', onBeforeInput),\n on(editable, 'input', onInput),\n on(document, 'selectionchange', onSelChange),\n on(editable, 'click', onCheckboxClick),\n on(editable, 'mouseup', fixChecklistCursor),\n on(editable, 'keyup', fixChecklistCursor),\n // Block drag-out and external drops in read-only mode.\n // D-1: Also block dragging of iframes and .an-video-wrapper elements in\n // edit mode — a user can inadvertently drag the iframe out of its wrapper\n // (making it playable/removable from contenteditable protection) by holding\n // the mouse and moving outside the wrapper before releasing.\n on(editable, 'dragstart', (e) => {\n if (isReadOnly()) { e.preventDefault(); return; }\n const target = e.target;\n if (target && (target.nodeName === 'IFRAME' ||\n (target.closest && target.closest('.an-video-wrapper')))) {\n e.preventDefault();\n }\n }),\n on(editable, 'drop', (e) => { if (isReadOnly()) e.preventDefault(); }),\n );\n\n // B-V: Re-apply superscript / subscript after IME composition ends.\n // Vietnamese and other IME-based inputs fire compositionstart/end around\n // the inserted characters. During composition the browser may place the\n // provisional text outside the current <sup>/<sub> element. When\n // compositionend fires we detect whether the cursor escaped the sup/sub\n // context and re-apply the command so the composed character stays inside.\n /** @type {string|null} 'superscript' | 'subscript' | null */\n let _compositionSupSub = null;\n const onCompositionStart = () => {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) { _compositionSupSub = null; return; }\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (node && node.closest) {\n if (node.closest('sup')) _compositionSupSub = 'superscript';\n else if (node.closest('sub')) _compositionSupSub = 'subscript';\n else _compositionSupSub = null;\n }\n };\n const onCompositionEnd = () => {\n const tag = _compositionSupSub;\n _compositionSupSub = null;\n if (!tag) return;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n const inContext = node && node.closest &&\n (tag === 'superscript' ? node.closest('sup') : node.closest('sub'));\n if (!inContext) {\n // The composed character escaped the sup/sub — re-apply the format.\n document.execCommand(tag);\n }\n };\n this._disposers.push(\n on(editable, 'compositionstart', onCompositionStart),\n on(editable, 'compositionend', onCompositionEnd),\n );\n }\n\n _onKeydown(event) {\n const editable = this.context.layoutInfo.editable;\n\n // Let Typing module handle special keys (Tab, Enter etc.)\n if (handleKeydown(event, editable, this.options)) return;\n\n // Built-in shortcuts\n if (isModifier(event, 'z') && !event.shiftKey) {\n event.preventDefault();\n this.undo();\n return;\n }\n if ((isModifier(event, 'z') && event.shiftKey) || isModifier(event, 'y')) {\n event.preventDefault();\n this.redo();\n return;\n }\n if (isModifier(event, 'b')) { event.preventDefault(); this.bold(); return; }\n if (isModifier(event, 'i')) { event.preventDefault(); this.italic(); return; }\n if (isModifier(event, 'u')) { event.preventDefault(); this.underline(); return; }\n if (isModifier(event, 'k')) { event.preventDefault(); this.context.invoke('linkDialog.show'); return; }\n\n // Ctrl+Shift+V — paste as plain text (signals Clipboard module)\n if (isModifier(event, 'v') && event.shiftKey) {\n this.context.invoke('clipboard.setForcePlain', true);\n return; // let the native paste event fire\n }\n\n // Show keyboard shortcuts dialog: Ctrl+Shift+/\n if (event.key === '/' && event.shiftKey && event.ctrlKey && !event.metaKey) {\n event.preventDefault();\n this.context.invoke('shortcutsDialog.show');\n return;\n }\n // Find: Ctrl+F\n if (isModifier(event, 'f')) {\n event.preventDefault();\n this.context.invoke('findReplace.show', 'find');\n return;\n }\n // Ctrl+H — Find & Replace\n if (isModifier(event, 'h')) {\n event.preventDefault();\n this.context.invoke('findReplace.show', 'replace');\n }\n // Ctrl+` — Inline Code\n if (isModifier(event, '`')) {\n event.preventDefault();\n this.inlineCode();\n }\n }\n\n // ---------------------------------------------------------------------------\n // Limit enforcement\n // ---------------------------------------------------------------------------\n\n /**\n * Called from beforeinput to block typing when char/word limits are reached.\n * Deletions and non-typing input types are always allowed.\n * @param {InputEvent} event\n */\n _enforceLimit(event) {\n const maxChars = this.options.maxChars || 0;\n const maxWords = this.options.maxWords || 0;\n if (!maxChars && !maxWords) return;\n\n const type = event.inputType || '';\n // Allow deletions, undo, redo and non-insert operations\n if (type.startsWith('delete') || type === 'historyUndo' || type === 'historyRedo') return;\n // Allow paste/drop — handled after the fact by Clipboard\n if (type === 'insertFromPaste' || type === 'insertFromDrop') return;\n // Only enforce for keyboard/IME/composition insertions\n if (!type.startsWith('insert')) return;\n\n const text = this.context.layoutInfo.editable.innerText || '';\n const chars = text.replace(/\\n/g, '').length;\n\n if (maxChars && chars >= maxChars) {\n event.preventDefault();\n if (typeof this.options.onCharLimitReached === 'function') {\n this.options.onCharLimitReached(this.context);\n }\n return;\n }\n\n // Word limit: block space / newline insertion when already at the limit\n if (maxWords && (event.data === ' ' || type === 'insertParagraph' || type === 'insertLineBreak')) {\n const words = text.trim() ? text.trim().split(/\\s+/).length : 0;\n if (words >= maxWords) {\n event.preventDefault();\n if (typeof this.options.onWordLimitReached === 'function') {\n this.options.onWordLimitReached(this.context);\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Post-command hook — records undo, fires change event\n // ---------------------------------------------------------------------------\n\n afterCommand() {\n // C4: Remove figure.an-figure elements whose <img> has been deleted so\n // orphaned figcaptions do not accumulate in the DOM.\n this._cleanOrphanedFigures();\n // Immediate: keep toolbar and statusbar in sync on every mutation.\n this.context.invoke('toolbar.refresh');\n this.context.invoke('statusbar.update');\n // Debounced: recording an undo snapshot and firing the change event require\n // a full innerHTML serialization. Batching rapid keystrokes prevents the\n // browser from re-serializing large content (e.g. embedded images) on every\n // single key press.\n this._scheduleSnapshot();\n }\n\n /**\n * Schedules a debounced undo snapshot + change event.\n * Resets the timer on each call so rapid typing produces one snapshot.\n */\n _scheduleSnapshot() {\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = setTimeout(() => {\n this._snapshotTimer = null;\n if (this._history) this._history.recordUndo();\n this.context.triggerEvent('change', this.getHTML());\n }, 400);\n }\n\n /**\n * C4: Removes figure.an-figure elements that no longer contain an <img>.\n * This happens when a user selects only the image (not the whole figure)\n * and deletes or replaces it, leaving a dangling figcaption.\n */\n _cleanOrphanedFigures() {\n const editable = this.context.layoutInfo.editable;\n editable.querySelectorAll('figure.an-figure').forEach((fig) => {\n if (!fig.querySelector('img')) {\n fig.parentNode.removeChild(fig);\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Focus management\n // ---------------------------------------------------------------------------\n\n focus() {\n const editable = this.context.layoutInfo.editable;\n editable.focus();\n }\n\n // ---------------------------------------------------------------------------\n // Content API\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the editor HTML content.\n * @returns {string}\n */\n getHTML() {\n // Strip zero-width spaces inserted after icons to allow caret placement.\n const raw = this.context.layoutInfo.editable.innerHTML.replace(/\\u200B/g, '');\n // Replace any blob: URLs (lightweight DOM references to pasted/dropped images)\n // with their original data URLs so the returned HTML is fully self-contained.\n return this.context.invoke('clipboard.resolveImages', raw) ?? raw;\n }\n\n /**\n * Sets the editor HTML content.\n * @param {string} html - HTML string (will be sanitised)\n */\n setHTML(html) {\n this.context.layoutInfo.editable.innerHTML = sanitiseHTML(html, { allowIframes: true });\n if (this._history) this._history.reset();\n this.afterCommand();\n }\n\n /**\n * Returns the editor plain text content.\n * @returns {string}\n */\n getText() {\n return this.context.layoutInfo.editable.innerText || '';\n }\n\n /**\n * Sets the editor content as plain text.\n * @param {string} text\n */\n setText(text) {\n this.context.layoutInfo.editable.textContent = text;\n if (this._history) this._history.reset();\n this.afterCommand();\n }\n\n /**\n * Clears the editor content.\n */\n clear() {\n this.setHTML('');\n }\n\n /**\n * Resets the undo/redo history stack.\n */\n clearHistory() {\n if (this._history) this._history.reset();\n }\n\n /**\n * Returns true when the editor has no meaningful content.\n * @returns {boolean}\n */\n isEmpty() {\n const text = (this.context.layoutInfo.editable.innerText || '')\n .trim()\n .replace(/\\u00a0/g, '');\n const hasMedia = !!this.context.layoutInfo.editable.querySelector('img, video, iframe, table');\n return !text && !hasMedia;\n }\n\n /**\n * Inserts HTML at the current cursor position.\n * @param {string} html\n */\n insertHTML(html) {\n if (!html) return;\n Style.execCommand('insertHTML', sanitiseHTML(html));\n this.afterCommand();\n }\n\n /**\n * Inserts plain text at the current cursor position.\n * @param {string} text\n */\n insertText(text) {\n if (!text) return;\n Style.execCommand('insertText', text);\n this.afterCommand();\n }\n\n /**\n * Sets editor content from a Markdown string.\n * @param {string} md\n */\n setMarkdown(md) {\n this.setHTML(markdownToHTML(md || ''));\n }\n\n /**\n * Returns the editor content as Markdown.\n * @returns {string}\n */\n getMarkdown() {\n return htmlToMarkdown(this.getHTML());\n }\n\n // ---------------------------------------------------------------------------\n // Undo / redo\n // ---------------------------------------------------------------------------\n\n undo() {\n if (this._history) {\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n this._history.undo();\n this.context.invoke('toolbar.refresh');\n this.context.invoke('statusbar.update');\n this.context.triggerEvent('change', this.getHTML());\n }\n }\n\n redo() {\n if (this._history) {\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n this._history.redo();\n this.context.invoke('toolbar.refresh');\n this.context.invoke('statusbar.update');\n this.context.triggerEvent('change', this.getHTML());\n }\n }\n\n canUndo() {\n return this._history ? this._history.canUndo() : false;\n }\n\n canRedo() {\n return this._history ? this._history.canRedo() : false;\n }\n\n // ---------------------------------------------------------------------------\n // Style commands (delegated to Style module)\n // ---------------------------------------------------------------------------\n\n bold() { Style.bold(); this.afterCommand(); }\n italic() { Style.italic(); this.afterCommand(); }\n underline() { Style.underline(); this.afterCommand(); }\n strikethrough() { Style.strikethrough(); this.afterCommand(); }\n superscript() { Style.superscript(); this.afterCommand(); }\n subscript() { Style.subscript(); this.afterCommand(); }\n justifyLeft() { Style.justifyLeft(); this.afterCommand(); }\n justifyCenter() { Style.justifyCenter(); this.afterCommand(); }\n justifyRight() { Style.justifyRight(); this.afterCommand(); }\n justifyFull() { Style.justifyFull(); this.afterCommand(); }\n indent() { Style.indent(); this.afterCommand(); }\n outdent() { Style.outdent(); this.afterCommand(); }\n insertUL() { Style.insertUnorderedList(); this.afterCommand(); }\n insertOL() { Style.insertOrderedList(); this.afterCommand(); }\n inlineCode() { Style.toggleInlineCode(this.context.layoutInfo.editable); this.afterCommand(); }\n toggleChecklist() { Style.toggleChecklist(); this.afterCommand(); }\n print() { this.context.print(); }\n\n /**\n * @param {string} tagName - e.g. 'h1', 'p', 'blockquote'\n */\n formatBlock(tagName) { Style.formatBlock(tagName); this.afterCommand(); }\n\n /**\n * @param {string} color\n */\n foreColor(color) { Style.foreColor(color); this.afterCommand(); }\n\n /**\n * @param {string} color\n */\n backColor(color) { Style.backColor(color); this.afterCommand(); }\n\n /**\n * @param {string} name\n */\n fontName(name) { Style.fontName(name); this.afterCommand(); }\n\n /**\n * @param {string} size - e.g. '14px'\n */\n fontSize(size) { Style.fontSize(size, this.context.layoutInfo.editable); this.afterCommand(); }\n\n // ---------------------------------------------------------------------------\n // Insert helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Inserts a horizontal rule at the cursor.\n */\n insertHr() {\n Style.execCommand('insertHorizontalRule');\n this.afterCommand();\n }\n\n /**\n * Creates a link at the current selection.\n * @param {string} url\n * @param {string} text\n * @param {boolean} [openInNewTab=false]\n */\n insertLink(url, text, openInNewTab = false) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const safeUrl = sanitiseUrl(url);\n if (!safeUrl) return;\n\n const hasText = sel.toString().trim().length > 0;\n if (!hasText) {\n const displayText = this._escapeAttr(text || safeUrl);\n Style.execCommand('insertHTML', `<a href=\"${this._escapeAttr(safeUrl)}\"${openInNewTab ? ' target=\"_blank\" rel=\"noopener noreferrer\"' : ''}>${displayText}</a>`);\n } else {\n Style.execCommand('createLink', safeUrl);\n if (openInNewTab) {\n const link = this._getClosestAnchor();\n if (link) {\n link.setAttribute('target', '_blank');\n link.setAttribute('rel', 'noopener noreferrer');\n }\n }\n }\n this.afterCommand();\n }\n\n /**\n * Removes the link from the selected anchor.\n */\n unlink() {\n Style.execCommand('unlink');\n this.afterCommand();\n }\n\n /**\n * Inserts an image.\n * @param {string} src - URL or data-URI\n * @param {string} [alt]\n */\n insertImage(src, alt = '', align = '') {\n const safeSrc = sanitiseUrl(src, { allowData: true });\n if (!safeSrc) return;\n const styleMap = {\n left: 'float:left;margin:0 1em 1em 0',\n center: 'display:block;margin:0 auto',\n right: 'float:right;margin:0 0 1em 1em',\n };\n const style = styleMap[align] || '';\n const styleAttr = style ? ` style=\"${style}\"` : '';\n Style.execCommand('insertHTML', `<img src=\"${this._escapeAttr(safeSrc)}\" alt=\"${this._escapeAttr(alt)}\" class=\"an-image\"${styleAttr}>`);\n this.afterCommand();\n }\n\n /**\n * Inserts a video embed (iframe or <video> element).\n * The html string is already validated/built by VideoDialog.\n * @param {string} html\n */\n insertVideo(html) {\n if (!html) return;\n Style.execCommand('insertHTML', html);\n this.afterCommand();\n }\n\n /**\n * Inserts a table.\n * @param {number} cols\n * @param {number} rows\n */\n insertTable(cols, rows) {\n insertTable(cols, rows, { headerRow: this.context.options.tableHeaderRow });\n this.afterCommand();\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n _getClosestAnchor() {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n let node = sel.getRangeAt(0).startContainer;\n while (node) {\n if (node.nodeName === 'A') return node;\n node = node.parentNode;\n }\n return null;\n }\n\n /**\n * Escapes a string for safe use inside an HTML attribute value.\n * @param {string} str\n * @returns {string}\n */\n _escapeAttr(str) {\n return String(str ?? '')\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n }\n\n // --- delegated to shared sanitise.js ---\n}\n","/**\n * Toolbar.js - Builds and manages the editor toolbar UI\n * Inspired by Summernote's Toolbar module — rewritten without jQuery\n */\n\nimport { createElement, on } from '../core/dom.js';\n\n// Module-level cache for FontAwesome detection.\n// Evaluated once per page load so all Toolbar instances on the same page agree\n// on whether the HOST PAGE included FA — regardless of whether IconDialog later\n// auto-injects its own FA <link> for the icon-picker glyph rendering.\nlet _faPageLevelReady = null;\n\n// ---------------------------------------------------------------------------\n// Module-level icon lookup tables — built once, shared across all instances.\n// Previously these were re-created inside _createButton() on every button\n// render, producing O(buttons × map-size) allocations per toolbar init.\n// ---------------------------------------------------------------------------\nconst _S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\nconst _svgWrap = (paths) =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${_S} style=\"display:block\">${paths}</svg>`;\n\nconst _SVG_MAP = new Map([\n // Format\n ['bold', _svgWrap('<path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/>')],\n ['italic', _svgWrap('<line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/>')],\n ['underline', _svgWrap('<path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/>')],\n ['strikethrough', _svgWrap('<path d=\"M17.3 12H6.7\"/><path d=\"M10 6.5C10 5.1 11.1 4 12.5 4c1.4 0 2.5 1.1 2.5 2.5 0 .8-.4 1.5-1 2\"/><path d=\"M14 17.5C14 19 12.9 20 11.5 20 10.1 20 9 18.9 9 17.5c0-.8.4-1.5 1-2\"/>')],\n ['superscript', _svgWrap('<path d=\"m4 19 8-8\"/><path d=\"m12 19-8-8\"/><path d=\"M20 12h-4c0-1.5.44-2 1.5-2.5S20 8.33 20 7.25C20 6 19 5 17.5 5S15 6 15 7\"/>')],\n ['subscript', _svgWrap('<path d=\"m4 5 8 8\"/><path d=\"m12 5-8 8\"/><path d=\"M20 21h-4c0-1.5.44-2 1.5-2.5S20 17.33 20 16.25C20 15 19 14 17.5 14S15 15 15 16\"/>')],\n // Alignment\n ['align-left', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"/>')],\n ['align-center', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"18\" y1=\"12\" x2=\"6\" y2=\"12\"/><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"/>')],\n ['align-right', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"/>')],\n ['align-justify', _svgWrap('<line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"12\" x2=\"3\" y2=\"12\"/><line x1=\"21\" y1=\"18\" x2=\"3\" y2=\"18\"/>')],\n // Lists\n ['list-ul', _svgWrap('<line x1=\"9\" y1=\"6\" x2=\"20\" y2=\"6\"/><line x1=\"9\" y1=\"12\" x2=\"20\" y2=\"12\"/><line x1=\"9\" y1=\"18\" x2=\"20\" y2=\"18\"/><circle cx=\"4\" cy=\"6\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"18\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/>')],\n ['list-ol', _svgWrap('<line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/><path d=\"M4 6h1V3\"/><path d=\"M4 10h2l-2 2h2\"/><path d=\"M4 16.5A1.5 1.5 0 0 1 5.5 15a1.5 1.5 0 0 1 0 3H4\"/>')],\n ['indent', _svgWrap('<polyline points=\"3 8 7 12 3 16\"/><line x1=\"21\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"21\" y1=\"6\" x2=\"11\" y2=\"6\"/><line x1=\"21\" y1=\"18\" x2=\"11\" y2=\"18\"/>')],\n ['outdent', _svgWrap('<polyline points=\"7 8 3 12 7 16\"/><line x1=\"21\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"21\" y1=\"6\" x2=\"11\" y2=\"6\"/><line x1=\"21\" y1=\"18\" x2=\"11\" y2=\"18\"/>')],\n // History\n ['undo', _svgWrap('<path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/>')],\n ['redo', _svgWrap('<path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/>')],\n // Insert\n ['minus', _svgWrap('<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>')],\n ['link', _svgWrap('<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>')],\n ['image', _svgWrap('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>')],\n ['video', _svgWrap('<polygon points=\"23 7 16 12 23 17 23 7\"/><rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\"/>')],\n ['table', _svgWrap('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/>')],\n ['emoji', _svgWrap('<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8.5 14.5s1.5 2.5 3.5 2.5 3.5-2.5 3.5-2.5\"/><circle cx=\"9\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>')],\n ['icon', _svgWrap('<circle cx=\"8\" cy=\"8\" r=\"3\"/><circle cx=\"16\" cy=\"8\" r=\"3\"/><rect x=\"5\" y=\"13\" width=\"6\" height=\"6\" rx=\"1\"/><rect x=\"13\" y=\"13\" width=\"6\" height=\"6\" rx=\"1\"/>')],\n // View\n ['code', _svgWrap('<polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/>')],\n ['expand', _svgWrap('<polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/>')],\n // Color pickers\n ['foreColor', _svgWrap('<path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/>')],\n ['backColor', _svgWrap('<path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/>')],\n ['keyboard', _svgWrap('<rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"2\"/><line x1=\"6\" y1=\"10\" x2=\"6\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"10\" y1=\"10\" x2=\"10\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"14\" y1=\"10\" x2=\"14\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"18\" y1=\"10\" x2=\"18\" y2=\"10\" stroke-width=\"2.5\"/><line x1=\"8\" y1=\"14\" x2=\"16\" y2=\"14\" stroke-width=\"2\"/>')],\n ['caption', _svgWrap('<rect x=\"3\" y=\"3\" width=\"18\" height=\"11\" rx=\"2\"/><line x1=\"6\" y1=\"18\" x2=\"18\" y2=\"18\"/><line x1=\"9\" y1=\"21\" x2=\"15\" y2=\"21\"/>')],\n ['remove-format', _svgWrap('<path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/>')],\n ['direction', _svgWrap('<path d=\"M12 20V4\"/><path d=\"m9 7-3 3 3 3\"/><path d=\"M4 10h8\"/><path d=\"m15 7 3 3-3 3\"/><path d=\"M20 10h-8\"/>')],\n ['search', _svgWrap('<circle cx=\"11\" cy=\"11\" r=\"7\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/>')],\n ['find-replace', _svgWrap('<circle cx=\"10\" cy=\"10\" r=\"6\"/><line x1=\"18\" y1=\"18\" x2=\"14.35\" y2=\"14.35\"/><path d=\"M16 19h6\"/><path d=\"M19 16v6\"/>')],\n ['inline-code', _svgWrap('<path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\"/><path d=\"M16 3h1a2 2 0 0 1 2 2v5c0 1.1.9 2 2 2a2 2 0 0 1-2 2v5a2 2 0 0 1-2 2h-1\"/>')],\n ['checklist', _svgWrap('<rect x=\"3\" y=\"4\" width=\"5\" height=\"5\" rx=\"1\"/><path d=\"m4 6.5 1 1 2-2\"/><rect x=\"3\" y=\"13\" width=\"5\" height=\"5\" rx=\"1\"/><line x1=\"10\" y1=\"6.5\" x2=\"21\" y2=\"6.5\"/><line x1=\"10\" y1=\"15.5\" x2=\"21\" y2=\"15.5\"/>')],\n ['print', _svgWrap('<path d=\"M6 9V2h12v7\"/><path d=\"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2\"/><rect x=\"6\" y=\"14\" width=\"12\" height=\"8\"/>')],\n]);\n\nconst _FA_MAP = new Map([\n ['bold', 'fa-bold'],\n ['italic', 'fa-italic'],\n ['underline', 'fa-underline'],\n ['strikethrough', 'fa-strikethrough'],\n ['superscript', 'fa-superscript'],\n ['subscript', 'fa-subscript'],\n ['align-left', 'fa-align-left'],\n ['align-center', 'fa-align-center'],\n ['align-right', 'fa-align-right'],\n ['align-justify', 'fa-align-justify'],\n ['list-ul', 'fa-list-ul'],\n ['list-ol', 'fa-list-ol'],\n ['indent', 'fa-indent'],\n ['outdent', 'fa-outdent'],\n ['undo', 'fa-rotate-left'],\n ['redo', 'fa-rotate-right'],\n ['minus', 'fa-minus'],\n ['link', 'fa-link'],\n ['image', 'fa-image'],\n ['code', 'fa-code'],\n ['expand', 'fa-expand'],\n ['emoji', 'fa-face-smile'],\n ['icon', 'fa-icons'],\n ['foreColor', 'fa-font'],\n ['backColor', 'fa-highlighter'],\n ['keyboard', 'fa-keyboard'],\n ['remove-format', 'fa-remove-format'],\n ['direction', 'fa-arrow-right-arrow-left'],\n ['search', 'fa-magnifying-glass'],\n ['find-replace', 'fa-magnifying-glass-plus'],\n ['inline-code', 'fa-code'],\n ['checklist', 'fa-list-check'],\n ['print', 'fa-print'],\n]);\n\nexport class Toolbar {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this.el = null;\n /** @type {Array<() => void>} disposers */\n this._disposers = [];\n /** @type {Array<() => void>} closers for all open color picker popups */\n this._colorPickerClosers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this.el = createElement('div', { class: 'an-toolbar' });\n // Detect FontAwesome once at toolbar build time to avoid re-querying the DOM\n // for every button rendered.\n this._faReady = this._detectFontAwesome();\n this._buildButtons();\n this._btnMap = new Map((this.options.toolbar || []).flat().map((b) => [b.name, b]));\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this.el && this.el.parentNode) {\n this.el.parentNode.removeChild(this.el);\n }\n this.el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildButtons() {\n const toolbar = this.options.toolbar || [];\n // Build into a DocumentFragment so all groups are appended in a single\n // DOM operation, avoiding one reflow per group.\n const fragment = document.createDocumentFragment();\n toolbar.forEach((group) => {\n const groupEl = createElement('div', { class: 'an-btn-group' });\n group.forEach((btnDef) => {\n let el;\n if (btnDef.type === 'select') el = this._createSelect(btnDef);\n else if (btnDef.type === 'grid') el = this._createGridPicker(btnDef);\n else if (btnDef.type === 'colorpicker') el = this._createColorPicker(btnDef);\n else el = this._createButton(btnDef);\n groupEl.appendChild(el);\n });\n fragment.appendChild(groupEl);\n });\n this.el.appendChild(fragment);\n }\n\n /**\n * Creates a table-grid picker button with a hoverable row/col selector popup.\n * @param {import('./Buttons.js').ButtonDef} def\n * @returns {HTMLDivElement}\n */\n _createGridPicker(def) {\n const ROWS = 10;\n const COLS = 10;\n\n const wrap = createElement('div', { class: 'an-table-picker-wrap' });\n\n const useBootstrap = !!this.options.useBootstrap;\n const baseClass = useBootstrap\n ? (this.options.toolbarButtonClass || 'btn btn-sm btn-light')\n : 'an-btn';\n const btn = createElement('button', {\n type: 'button',\n class: baseClass,\n title: this.context.locale.toolbar[def.name] || def.tooltip || '',\n 'data-btn': def.name,\n 'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,\n 'aria-haspopup': 'true',\n 'aria-expanded': 'false',\n });\n\n // Set icon — inline SVG (table) with optional FontAwesome fallback\n if (this._faReady) {\n const faPrefix = this.options.fontAwesomeClass || 'fas';\n btn.innerHTML = `<i class=\"${faPrefix} fa-table\" aria-hidden=\"true\"></i>`;\n } else {\n const S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\n btn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${S} style=\"display:block\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>`;\n }\n\n // Popup\n const popup = createElement('div', {\n class: 'an-table-picker-popup',\n role: 'dialog',\n 'aria-label': 'Select table size',\n });\n const grid = createElement('div', { class: 'an-table-grid' });\n const label = createElement('div', { class: 'an-table-label' });\n label.textContent = this.context.locale.toolbar.insertTableLabel || 'Insert Table';\n\n const cells = [];\n for (let r = 1; r <= ROWS; r++) {\n for (let c = 1; c <= COLS; c++) {\n const cell = createElement('div', {\n class: 'an-table-cell',\n 'data-row': String(r),\n 'data-col': String(c),\n });\n cells.push(cell);\n grid.appendChild(cell);\n }\n }\n\n popup.appendChild(grid);\n popup.appendChild(label);\n\n let isOpen = false;\n\n const setHighlight = (rows, cols) => {\n cells.forEach((cell) => {\n const r = +cell.getAttribute('data-row');\n const c = +cell.getAttribute('data-col');\n cell.classList.toggle('active', r <= rows && c <= cols);\n });\n label.textContent = (rows && cols) ? `${rows} × ${cols}` : (this.context.locale.toolbar.insertTableLabel || 'Insert Table');\n };\n\n const openPopup = () => {\n isOpen = true;\n popup.style.display = 'block';\n btn.setAttribute('aria-expanded', 'true');\n };\n\n const closePopup = () => {\n isOpen = false;\n popup.style.display = 'none';\n btn.setAttribute('aria-expanded', 'false');\n setHighlight(0, 0);\n };\n\n const d1 = on(btn, 'click', (e) => {\n e.stopPropagation();\n if (isOpen) closePopup(); else openPopup();\n });\n\n const d2 = on(grid, 'mouseover', (e) => {\n const cell = e.target.closest('.an-table-cell');\n if (!cell) return;\n setHighlight(+cell.getAttribute('data-row'), +cell.getAttribute('data-col'));\n });\n\n const d3 = on(grid, 'mouseleave', () => setHighlight(0, 0));\n\n const d4 = on(grid, 'click', (e) => {\n const cell = e.target.closest('.an-table-cell');\n if (!cell) return;\n const rows = +cell.getAttribute('data-row');\n const cols = +cell.getAttribute('data-col');\n closePopup();\n this.context.invoke('editor.focus');\n def.action(this.context, rows, cols);\n });\n\n const d5 = on(document, 'click', () => { if (isOpen) closePopup(); });\n\n this._disposers.push(d1, d2, d3, d4, d5);\n\n wrap.appendChild(btn);\n wrap.appendChild(popup);\n return wrap;\n }\n\n /**\n * Creates a split color-picker widget:\n * [icon + strip | ▾] — left applies current color, right opens swatch popup.\n * @param {{ name: string, type: 'colorpicker', tooltip: string, defaultColor: string, action: Function }} def\n * @returns {HTMLDivElement}\n */\n _createColorPicker(def) {\n const PRESETS = [\n // Grayscale\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n // Saturated\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n // Pastel\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\n ];\n\n let currentColor = def.defaultColor || '#000000';\n\n const wrap = createElement('div', { class: 'an-color-picker-wrap' });\n\n const useBootstrap = !!this.options.useBootstrap;\n const baseClass = useBootstrap ? (this.options.toolbarButtonClass || 'btn btn-sm btn-light') : 'an-btn';\n\n // ---- Apply button (icon + color strip) ----\n const applyBtn = createElement('button', {\n type: 'button',\n class: `${baseClass} an-color-btn`,\n title: this.context.locale.toolbar[def.name] || def.tooltip || '',\n 'data-btn': def.name,\n 'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,\n });\n\n const S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\n const iconSvg = def.name === 'foreColor'\n ? `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${S} style=\"display:block\"><path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/></svg>`\n : `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" ${S} style=\"display:block\"><path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/></svg>`;\n\n applyBtn.innerHTML = iconSvg;\n const strip = createElement('span', { class: 'an-color-strip' });\n strip.style.background = currentColor;\n applyBtn.appendChild(strip);\n\n // ---- Arrow button (open popup) ----\n const arrowBtn = createElement('button', {\n type: 'button',\n class: `${baseClass} an-color-arrow`,\n title: def.name === 'foreColor'\n ? (this.context.locale.toolbar.chooseTextColor || 'Choose text color')\n : (this.context.locale.toolbar.chooseHighlightColor || 'Choose highlight color'),\n 'aria-haspopup': 'true',\n 'aria-expanded': 'false',\n });\n arrowBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"8\" height=\"8\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" style=\"display:block\"><path d=\"M7 10l5 5 5-5H7z\"/></svg>`;\n\n // ---- Popup ----\n const popup = createElement('div', { class: 'an-color-popup' });\n popup.style.display = 'none';\n\n const swatches = createElement('div', { class: 'an-color-swatches' });\n const userSwatches = Array.isArray(this.options.colorSwatches) ? this.options.colorSwatches : [];\n const allColors = [...new Set([...userSwatches, ...PRESETS])];\n allColors.forEach((color) => {\n const sw = createElement('div', { class: 'an-color-swatch', title: color, 'data-color': color });\n sw.style.background = color;\n swatches.appendChild(sw);\n });\n\n const customRow = createElement('div', { class: 'an-color-custom' });\n const colorInput = createElement('input', { type: 'color', value: currentColor, title: this.context.locale.toolbar.customColor || 'Custom color' });\n const customLabel = createElement('span', {}, [this.context.locale.toolbar.customColor || 'Custom color']);\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n\n popup.appendChild(swatches);\n popup.appendChild(customRow);\n\n // ---- State ----\n let isOpen = false;\n /** @type {Range|null} saved selection range before popup opens */\n let savedRange = null;\n\n const saveSelection = () => {\n const sel = window.getSelection();\n savedRange = (sel && sel.rangeCount) ? sel.getRangeAt(0).cloneRange() : null;\n };\n\n const restoreSelection = () => {\n if (!savedRange) return;\n try {\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(savedRange);\n } catch (_) {\n // Range target may be detached if DOM changed while popup was open\n }\n };\n\n const openPopup = () => {\n // Close any other open color picker before opening this one\n this._colorPickerClosers.forEach((fn) => { if (fn !== closePopup) fn(); });\n saveSelection();\n isOpen = true;\n // Use fixed positioning so the popup escapes any overflow-clipping ancestor\n // (notably toolbar scroll mode, where overflow-x:auto coerces overflow-y)\n const rect = arrowBtn.getBoundingClientRect();\n const popupMinW = 184;\n let left = rect.left;\n if (left + popupMinW > window.innerWidth) left = rect.right - popupMinW;\n popup.style.top = `${rect.bottom + 4}px`;\n popup.style.left = `${Math.max(4, left)}px`;\n popup.style.display = 'block';\n arrowBtn.setAttribute('aria-expanded', 'true');\n };\n\n const closePopup = () => {\n isOpen = false;\n popup.style.display = 'none';\n popup.style.top = '';\n popup.style.left = '';\n arrowBtn.setAttribute('aria-expanded', 'false');\n };\n\n const applyColor = (color) => {\n currentColor = color;\n strip.style.background = color;\n colorInput.value = color;\n restoreSelection();\n def.action(this.context, color);\n this.context.invoke('editor.afterCommand');\n closePopup();\n };\n\n const d1 = on(applyBtn, 'click', (e) => {\n e.preventDefault();\n restoreSelection();\n def.action(this.context, currentColor);\n this.context.invoke('editor.afterCommand');\n });\n\n const d2 = on(arrowBtn, 'mousedown', (e) => {\n // Prevent editor blur so selection is preserved when the popup opens\n e.preventDefault();\n });\n\n const d2b = on(arrowBtn, 'click', (e) => {\n e.stopPropagation();\n if (isOpen) closePopup(); else openPopup();\n });\n\n const d3 = on(swatches, 'mousedown', (e) => {\n // Prevent blur before the click handler fires\n e.preventDefault();\n });\n\n const d3b = on(swatches, 'click', (e) => {\n const sw = e.target.closest('.an-color-swatch');\n if (sw) applyColor(sw.dataset.color);\n });\n\n const d4 = on(colorInput, 'change', (e) => {\n applyColor(e.target.value);\n });\n\n const d5 = on(document, 'click', (e) => {\n // popup is in document.body, not inside wrap — check both\n if (isOpen && !wrap.contains(e.target) && !popup.contains(e.target)) closePopup();\n });\n\n const d6 = on(popup, 'click', (e) => e.stopPropagation());\n\n // Close the popup when the viewport scrolls or resizes so the fixed-position\n // popup doesn't drift away from the button it belongs to.\n const onScrollResize = () => { if (isOpen) closePopup(); };\n document.addEventListener('scroll', onScrollResize, { passive: true, capture: true });\n window.addEventListener('resize', onScrollResize, { passive: true });\n\n this._disposers.push(d1, d2, d2b, d3, d3b, d4, d5, d6,\n () => document.removeEventListener('scroll', onScrollResize, { capture: true }),\n () => window.removeEventListener('resize', onScrollResize),\n // Remove popup from body on editor destroy\n () => { if (popup.parentNode) popup.parentNode.removeChild(popup); },\n );\n\n // Register this popup's closer so other color pickers can close it\n this._colorPickerClosers.push(closePopup);\n this._disposers.push(() => {\n const idx = this._colorPickerClosers.indexOf(closePopup);\n if (idx !== -1) this._colorPickerClosers.splice(idx, 1);\n });\n\n // Append popup to document.body so it escapes all overflow-clipping and\n // contain:layout ancestors (contain:layout makes the container a fixed-pos\n // containing block per the CSS Contain spec, breaking viewport coordinates).\n wrap.appendChild(applyBtn);\n wrap.appendChild(arrowBtn);\n document.body.appendChild(popup);\n return wrap;\n }\n\n /**\n * Creates a <select> dropdown for font-family (or similar) options.\n * @param {import('./Buttons.js').DropdownDef} def\n * @returns {HTMLSelectElement}\n */\n _createSelect(def) {\n const items = (def.name === 'fontFamily')\n ? (this.options.fontFamilies || [])\n : (def.items || []);\n\n const cls = def.selectClass ? `an-select ${def.selectClass}` : 'an-select';\n const select = createElement('select', {\n class: cls,\n title: this.context.locale.toolbar[def.name] || def.tooltip || '',\n 'data-btn': def.name,\n 'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,\n });\n\n // Blank \"placeholder\" option (non-selectable header)\n const placeholderText = this.context.locale.toolbar[def.name + 'Placeholder'] || def.placeholder || 'Font';\n const placeholder = createElement('option', { value: '', disabled: '', hidden: '' }, [placeholderText]);\n select.appendChild(placeholder);\n\n items.forEach((item) => {\n const value = (typeof item === 'object') ? item.value : item;\n const label = (typeof item === 'object')\n ? (def.name === 'paragraphStyle'\n ? ((this.context.locale.toolbar.paragraphItems || {})[item.value] || item.label)\n : item.label)\n : item;\n const isHeader = (typeof item === 'object') && !!item.disabled;\n const attrs = { value };\n if (isHeader) attrs.disabled = '';\n const opt = createElement('option', attrs, [label]);\n // Only apply fontFamily face preview on real (non-header) entries\n if (def.name === 'fontFamily' && !isHeader) opt.style.fontFamily = value;\n select.appendChild(opt);\n });\n\n // Save the editor selection when the user starts interacting with the\n // dropdown (mousedown fires before the editor loses focus). When the\n // change handler runs, focus has moved to the <select>; we restore the\n // saved range so execCommand / fontSize() act on the intended text.\n /** @type {Range|null} */\n let _savedRange = null;\n const dMousedown = on(select, 'mousedown', () => {\n const sel = window.getSelection();\n _savedRange = (sel && sel.rangeCount) ? sel.getRangeAt(0).cloneRange() : null;\n });\n\n const disposer = on(select, 'change', (e) => {\n const value = /** @type {HTMLSelectElement} */ (e.target).value;\n const selectedOpt = /** @type {HTMLSelectElement} */ (e.target).options[/** @type {HTMLSelectElement} */ (e.target).selectedIndex];\n if (!value || selectedOpt.disabled) return;\n this.context.invoke('editor.focus');\n // Restore selection saved on mousedown so the action targets the correct text.\n if (_savedRange) {\n try {\n const sel = window.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(_savedRange); }\n } catch (_) { /* range may be stale if DOM changed */ }\n }\n def.action(this.context, value);\n this.context.invoke('editor.afterCommand');\n });\n\n this._disposers.push(dMousedown, disposer);\n return select;\n }\n\n /**\n * @param {import('./Buttons.js').ButtonDef} btnDef\n * @returns {HTMLButtonElement}\n */\n _createButton(btnDef) {\n // Determine classes based on whether the consumer wants Bootstrap styling\n const useBootstrap = !!this.options.useBootstrap;\n const baseClass = useBootstrap ? (this.options.toolbarButtonClass || 'btn btn-sm btn-light') : `an-btn`;\n const extra = btnDef.className ? ` ${btnDef.className}` : '';\n const classAttr = `${baseClass}${extra}`;\n\n const btn = createElement('button', {\n type: 'button',\n class: classAttr,\n title: this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || '',\n 'data-btn': btnDef.name,\n 'aria-label': this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || btnDef.name,\n });\n\n // Render icon: prefer FontAwesome if enabled; otherwise fall back to SVG or text.\n const faPrefix = this.options.fontAwesomeClass || 'fas';\n const useFaNow = this._faReady;\n if (useFaNow) {\n const faName = _FA_MAP.get(btnDef.icon) || _FA_MAP.get(btnDef.name) || null;\n if (faName) {\n btn.innerHTML = `<i class=\"${faPrefix} ${faName}\" aria-hidden=\"true\"></i>`;\n } else if (_SVG_MAP.has(btnDef.icon)) {\n btn.innerHTML = _SVG_MAP.get(btnDef.icon);\n } else {\n btn.textContent = btnDef.icon || btnDef.name;\n }\n } else {\n // FontAwesome absent: use SVG fallback when available\n if (_SVG_MAP.has(btnDef.icon)) {\n btn.innerHTML = _SVG_MAP.get(btnDef.icon);\n } else if (_SVG_MAP.has(btnDef.name)) {\n btn.innerHTML = _SVG_MAP.get(btnDef.name);\n } else {\n btn.textContent = btnDef.icon || btnDef.name;\n }\n }\n\n const disposer = on(btn, 'click', (event) => {\n event.preventDefault();\n // Restore focus to the editor before executing the action\n this.context.invoke('editor.focus');\n btnDef.action(this.context);\n this.context.invoke('editor.afterCommand');\n this.refresh();\n });\n\n this._disposers.push(disposer);\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // FontAwesome detection (run once at initialize time)\n // ---------------------------------------------------------------------------\n\n _detectFontAwesome() {\n if (!this.options.useFontAwesome) return false;\n // Return cached result when available. This ensures that a later-initialised\n // toolbar sees the same detection state as the first one — even if IconDialog\n // has since injected its own FA <link> into <head> for the icon-picker UI.\n if (_faPageLevelReady !== null) return _faPageLevelReady;\n if (document.querySelector('.fa, .fas, .far, .fal, .fab, .fa-solid')) {\n _faPageLevelReady = true;\n return true;\n }\n // Exclude the editor-self-injected link (id='an-fontawesome-css') so it doesn't\n // count as \"the host page loaded FA\" for toolbar icon rendering purposes.\n const links = Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]'))\n .filter((l) => l.id !== 'an-fontawesome-css')\n .map((l) => l.href || '').join(' ');\n _faPageLevelReady = /fontawesome|font-awesome|use\\.fontawesome|all\\.css/.test(links);\n return _faPageLevelReady;\n }\n\n // ---------------------------------------------------------------------------\n // State refresh (active / disabled states)\n // ---------------------------------------------------------------------------\n\n refresh() {\n if (!this.el) return;\n const btnMap = this._btnMap || new Map();\n\n // Sync button active states\n this.el.querySelectorAll('button[data-btn]').forEach((btn) => {\n const def = btnMap.get(btn.getAttribute('data-btn'));\n if (def && typeof def.isActive === 'function') {\n btn.classList.toggle('active', !!def.isActive(this.context));\n }\n if (def && typeof def.isDisabled === 'function') {\n btn.disabled = !!def.isDisabled(this.context);\n }\n });\n\n // Sync select dropdowns (e.g. font family) with current cursor position\n this.el.querySelectorAll('select[data-btn]').forEach((select) => {\n const def = btnMap.get(select.getAttribute('data-btn'));\n if (!def || typeof def.getValue !== 'function') return;\n // queryCommandValue returns the font name, possibly quoted — strip quotes\n let raw = (def.getValue(this.context) || '').replace(/[\"']/g, '').trim();\n // Fallback: when no selection/font set, use the configured default font\n if (!raw) {\n raw = this.options.defaultFontFamily\n || (this.options.fontFamilies && this.options.fontFamilies[0])\n || '';\n }\n // Try to match against available options (case-insensitive)\n const matched = Array.from(select.options).find(\n (opt) => opt.value && opt.value.toLowerCase() === raw.toLowerCase()\n );\n select.value = matched ? matched.value : '';\n });\n }\n\n /**\n * Shows the toolbar.\n */\n show() {\n if (this.el) this.el.style.display = '';\n }\n\n /**\n * Hides the toolbar.\n */\n hide() {\n if (this.el) this.el.style.display = 'none';\n }\n}\n","/**\n * Statusbar.js - Displays word count, character count and resize handle\n * Inspired by Summernote's Statusbar module — rewritten without jQuery\n */\n\nimport { createElement, on } from '../core/dom.js';\nimport { debounce } from '../core/func.js';\n\n// Cache the segmenter instance at module level to avoid per-call allocation\nconst _segmenter =\n typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function'\n ? new Intl.Segmenter(undefined, { granularity: 'word' })\n : null;\n\n/**\n * Count words in a string, CJK-aware.\n * Uses Intl.Segmenter (Chromium 87+, Firefox 125+, Safari 17+) when available,\n * falling back to a simple whitespace split for older environments.\n * @param {string} text\n * @returns {number}\n */\nfunction _countWords(text) {\n const trimmed = text.trim();\n if (!trimmed) return 0;\n if (_segmenter) {\n let count = 0;\n for (const seg of _segmenter.segment(trimmed)) {\n if (seg.isWordLike) count++;\n }\n return count;\n }\n // Fallback: split on whitespace\n return trimmed.split(/\\s+/).length;\n}\n\n/**\n * Toggles warning/exceeded CSS classes on a count element.\n * @param {HTMLElement} el\n * @param {number} current\n * @param {number} limit 0 = no limit\n */\nfunction _applyLimitClass(el, current, limit) {\n if (!limit) {\n el.classList.remove('an-count-warn', 'an-count-exceeded');\n return;\n }\n if (current > limit) {\n el.classList.add('an-count-exceeded');\n el.classList.remove('an-count-warn');\n } else if (current >= limit * 0.9) {\n el.classList.add('an-count-warn');\n el.classList.remove('an-count-exceeded');\n } else {\n el.classList.remove('an-count-warn', 'an-count-exceeded');\n }\n}\n\nexport class Statusbar {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this.el = null;\n this._disposers = [];\n /** @type {HTMLElement|null} */\n this._wordCountEl = null;\n /** @type {HTMLElement|null} */\n this._charCountEl = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this.el = createElement('div', { class: 'an-statusbar' });\n\n // Resize handle\n if (this.options.resizable !== false) {\n const handle = createElement('div', {\n class: 'an-resize-handle',\n title: this.context.locale.statusbar.resizeHandle,\n 'aria-hidden': 'true',\n });\n this._bindResize(handle);\n this.el.appendChild(handle);\n }\n\n // Counters\n this._wordCountEl = createElement('span', { class: 'an-word-count' });\n this._charCountEl = createElement('span', { class: 'an-char-count' });\n const info = createElement('div', { class: 'an-status-info' });\n info.appendChild(this._wordCountEl);\n info.appendChild(this._charCountEl);\n this.el.appendChild(info);\n\n this._bindContentEvents();\n this.update();\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dragDisposers) {\n this._dragDisposers.forEach((d) => d());\n this._dragDisposers = null;\n }\n if (this.el && this.el.parentNode) {\n this.el.parentNode.removeChild(this.el);\n }\n this.el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Resize logic\n // ---------------------------------------------------------------------------\n\n _bindResize(handle) {\n let startY = 0;\n let startH = 0;\n // Resize the container (flex column parent) so that the editable — which\n // has flex:1 / flex-basis:0 — automatically fills the remaining space.\n // Setting height directly on a flex:1 item has no effect because the flex\n // algorithm ignores the height property when flex-basis is non-auto.\n const containerEl = this.context.layoutInfo.container;\n\n const applyDelta = (clientY) => {\n const delta = clientY - startY;\n // Compute the true minimum: fixed elements (toolbar + statusbar) must fit\n // inside the container. Sum the offsetHeight of every child that is NOT\n // the editable area, then add a small floor so the editable stays visible.\n const MIN_EDITABLE = 40;\n const fixedH = Array.from(containerEl.children)\n .filter(child => !child.classList.contains('an-editable'))\n .reduce((sum, child) => sum + child.offsetHeight, 0);\n const trueMin = Math.max(this.options.minHeight || 100, fixedH + MIN_EDITABLE);\n containerEl.style.height = `${Math.max(trueMin, startH + delta)}px`;\n };\n\n // Mouse drag\n const onMouseMove = (event) => applyDelta(event.clientY);\n\n const onMouseUp = () => {\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n this._dragDisposers = null;\n };\n\n const onMouseDown = (event) => {\n startY = event.clientY;\n startH = containerEl.offsetHeight;\n // Clear the editable's inline min-height so the flex layout can compress\n // it freely once the container has a fixed height. Without this, the\n // editable's min-height (set from options.height) overflows the container\n // when the user drags the handle to a size smaller than that value.\n this.context.layoutInfo.editable.style.minHeight = '';\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n // Track drag-phase listeners so destroy() can remove them mid-drag\n this._dragDisposers = [\n () => document.removeEventListener('mousemove', onMouseMove),\n () => document.removeEventListener('mouseup', onMouseUp),\n ];\n event.preventDefault();\n };\n\n // Touch drag\n const onTouchMove = (event) => {\n const touch = event.touches[0];\n if (touch) { event.preventDefault(); applyDelta(touch.clientY); }\n };\n\n const onTouchEnd = () => {\n document.removeEventListener('touchmove', onTouchMove);\n document.removeEventListener('touchend', onTouchEnd);\n this._dragDisposers = null;\n };\n\n const onTouchStart = (event) => {\n const touch = event.touches[0];\n if (!touch) return;\n startY = touch.clientY;\n startH = containerEl.offsetHeight;\n // Same as onMouseDown: clear editable min-height so flex can compress it\n this.context.layoutInfo.editable.style.minHeight = '';\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', onTouchEnd);\n this._dragDisposers = [\n () => document.removeEventListener('touchmove', onTouchMove),\n () => document.removeEventListener('touchend', onTouchEnd),\n ];\n };\n\n const d1 = on(handle, 'mousedown', onMouseDown);\n const d2 = on(handle, 'touchstart', onTouchStart);\n this._disposers.push(d1, d2);\n }\n\n // ---------------------------------------------------------------------------\n // Counter update\n // ---------------------------------------------------------------------------\n\n _bindContentEvents() {\n const editable = this.context.layoutInfo.editable;\n const updateDebounced = debounce(() => this.update(), 200);\n const d = on(editable, 'input', updateDebounced);\n this._disposers.push(d);\n }\n\n update() {\n if (!this._wordCountEl || !this._charCountEl) return;\n const editable = this.context.layoutInfo.editable;\n const text = editable.innerText || '';\n const words = _countWords(text);\n const chars = text.replace(/\\n/g, '').length;\n const maxWords = this.options.maxWords || 0;\n const maxChars = this.options.maxChars || 0;\n\n const LS = this.context.locale.statusbar;\n this._wordCountEl.textContent = maxWords\n ? LS.wordsLimit(words, maxWords)\n : LS.words(words);\n this._charCountEl.textContent = maxChars\n ? LS.charsLimit(chars, maxChars)\n : LS.chars(chars);\n\n // Apply warning / exceeded styles\n _applyLimitClass(this._wordCountEl, words, maxWords);\n _applyLimitClass(this._charCountEl, chars, maxChars);\n }\n\n /**\n * Returns the current word count of the editor content.\n * @returns {number}\n */\n getWordCount() {\n const editable = this.context.layoutInfo.editable;\n return _countWords(editable.innerText || '');\n }\n\n /**\n * Returns the current character count (excluding newlines) of the editor content.\n * @returns {number}\n */\n getCharCount() {\n const editable = this.context.layoutInfo.editable;\n return ((editable.innerText || '').replace(/\\n/g, '')).length;\n }\n}\n","/**\n * Clipboard.js - Handles paste events to strip unwanted formatting,\n * and paste/drop of image files.\n * Inspired by Summernote's Clipboard module\n */\n\nimport { on } from '../core/dom.js';\nimport { execCommand } from '../editing/Style.js';\nimport { sanitiseHTML } from '../core/sanitise.js';\nimport { isMarkdown, markdownToHTML } from '../core/markdown.js';\n\nexport class Clipboard {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n }\n\n initialize() {\n /** @type {Map<string, string>} Maps blob: URL (in DOM) → data: URL (serialisable) */\n this._blobRegistry = new Map();\n /** @type {boolean} Set to true by Ctrl+Shift+V shortcut to force one-shot plain paste */\n this._forcePlain = false;\n const editable = this.context.layoutInfo.editable;\n this._disposers.push(\n on(editable, 'paste', (e) => this._onPaste(e)),\n on(editable, 'dragover', (e) => this._onDragover(e)),\n on(editable, 'drop', (e) => this._onDrop(e)),\n );\n\n // Watch for removed images so their blob: URLs are revoked immediately,\n // preventing memory leaks during long editing sessions.\n this._mutationObserver = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.removedNodes) {\n this._revokeRemovedBlobs(node);\n }\n }\n });\n this._mutationObserver.observe(editable, { childList: true, subtree: true });\n\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._mutationObserver) {\n this._mutationObserver.disconnect();\n this._mutationObserver = null;\n }\n // Release any remaining object URLs\n if (this._blobRegistry) {\n this._blobRegistry.forEach((_, blobUrl) => URL.revokeObjectURL(blobUrl));\n this._blobRegistry.clear();\n }\n }\n\n /**\n * Revokes blob URLs for any <img> elements removed from the DOM.\n * @param {Node} node\n */\n _revokeRemovedBlobs(node) {\n if (!this._blobRegistry || !this._blobRegistry.size) return;\n const imgs = [];\n if (node.nodeName === 'IMG') {\n imgs.push(node);\n } else if (node.querySelectorAll) {\n imgs.push(...node.querySelectorAll('img'));\n }\n imgs.forEach((img) => {\n const src = img.getAttribute('src') || '';\n if (src.startsWith('blob:') && this._blobRegistry.has(src)) {\n URL.revokeObjectURL(src);\n this._blobRegistry.delete(src);\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Paste handler\n // ---------------------------------------------------------------------------\n\n /**\n * Strips Microsoft Word / Office HTML artefacts from a pasted HTML string.\n * Removes conditional comments, Office namespace elements, MsoXxx classes,\n * mso-* inline style rules, and empty paragraphs left behind by Word.\n * @param {string} html\n * @returns {string}\n */\n _cleanWordHtml(html) {\n return html\n // Conditional comments <!--[if ...]>...<![endif]-->\n .replace(/<!--\\[if[\\s\\S]*?\\[endif\\]-->/gi, '')\n // XML data blobs <xml>...</xml>\n .replace(/<xml[\\s\\S]*?<\\/xml>/gi, '')\n // XML processing instructions <?xml ... ?>\n .replace(/<\\?xml[\\s\\S]*?\\?>/gi, '')\n // Office namespace elements: <o:p>, <w:sDt>, <m:oMath>, <v:shape> …\n .replace(/<\\/?(o|w|m|v|st1):[a-z][^>]*>/gi, '')\n // MsoNormal, MsoBodyText, etc. class attributes\n .replace(/\\s+class=\"Mso[^\"]*\"/gi, '')\n // mso-* properties inside inline style attributes\n .replace(/\\s+style=\"([^\"]*)\"/gi, (_m, style) => {\n const cleaned = style.split(';')\n .map((s) => s.trim())\n .filter((s) => s && !/^mso-/i.test(s) && !/^(tab-stops|margin-[a-z]+-alt)/i.test(s))\n .join('; ');\n return cleaned ? ` style=\"${cleaned}\"` : '';\n })\n // Empty paragraphs Word sprinkles everywhere\n .replace(/<p[^>]*>\\s*( )?\\s*<\\/p>/gi, '');\n }\n\n /**\n * Detects and strips noise from social media sites (Facebook, X/Twitter, LinkedIn, etc.).\n * These React-based pages produce HTML with utility class names like `x1n2onr6` / `r-bcqeeo`,\n * `data-testid`, `data-lexical-*`, etc. We keep the semantic structure but remove all the noise.\n * @param {string} html\n * @returns {string}\n */\n _cleanSocialHtml(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n // Unwrap purely presentational wrapper spans/divs with no semantic meaning.\n // Single-pass reverse traversal: querySelectorAll returns elements in document\n // order, so iterating backwards processes innermost elements first — once a\n // child is unwrapped its parent may become unwrappable in the same pass.\n // This replaces the previous O(n²) while-loop that re-queried the whole tree\n // on every iteration.\n const candidates = Array.from(doc.querySelectorAll('span, div'));\n for (let i = candidates.length - 1; i >= 0; i--) {\n const el = candidates[i];\n if (!el.parentNode) continue; // already detached by an earlier iteration\n // Keep if it contains any semantic child element\n if (el.querySelector('a, strong, em, b, i, ul, ol, li, table, img, blockquote, pre, code, h1, h2, h3, h4, h5, h6')) continue;\n // Unwrap — replace el with its children\n const parent = el.parentNode;\n while (el.firstChild) parent.insertBefore(el.firstChild, el);\n parent.removeChild(el);\n }\n // Strip class and all data-* attributes from every remaining element\n doc.querySelectorAll('*').forEach((el) => {\n el.removeAttribute('class');\n el.removeAttribute('id');\n Array.from(el.attributes)\n .filter((a) => a.name.startsWith('data-') || a.name.startsWith('aria-'))\n .forEach((a) => el.removeAttribute(a.name));\n });\n return doc.body.innerHTML;\n }\n\n /**\n * Strips presentational attributes (class, style, data-*, id) from all elements,\n * keeping only semantic structure and URL attributes.\n * Used when `pasteStripAttributes` option is true.\n * @param {string} html\n * @returns {string}\n */\n _stripAttributes(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n const KEEP_ATTRS = new Set(['href', 'src', 'alt', 'target', 'rel', 'colspan', 'rowspan', 'type']);\n doc.querySelectorAll('*').forEach((el) => {\n Array.from(el.attributes)\n .filter((a) => !KEEP_ATTRS.has(a.name))\n .forEach((a) => el.removeAttribute(a.name));\n });\n return doc.body.innerHTML;\n }\n\n /**\n * Forces the next paste operation to strip all HTML formatting.\n * Called by Editor when Ctrl+Shift+V is pressed.\n * @param {boolean} val\n */\n setForcePlain(val) {\n this._forcePlain = !!val;\n }\n\n _onPaste(event) {\n const clipboardData = event.clipboardData || window.clipboardData;\n if (!clipboardData) return;\n\n // Consume and reset the one-shot plain-paste flag\n const forcePlain = this._forcePlain;\n this._forcePlain = false;\n\n // 1. Image file in clipboard (screenshot, copy-image-from-browser, etc.)\n if (clipboardData.items) {\n const imageItems = Array.from(clipboardData.items).filter(\n (item) => item.kind === 'file' && item.type.startsWith('image/'),\n );\n if (imageItems.length > 0) {\n event.preventDefault();\n const files = imageItems.map((item) => item.getAsFile()).filter(Boolean);\n this._insertImageFiles(files);\n return;\n }\n }\n\n // Fire onPaste hook so consumers can observe / intercept\n if (typeof this.options.onPaste === 'function') {\n this.options.onPaste({\n text: clipboardData.getData('text/plain') || '',\n html: clipboardData.types.includes('text/html') ? clipboardData.getData('text/html') : null,\n });\n }\n\n // 2. Force plain-text only — strip all formatting\n if (forcePlain || this.options.pasteAsPlainText) {\n event.preventDefault();\n const text = clipboardData.getData('text/plain');\n const html = text\n .split(/\\r?\\n/)\n .map((line) => `<p>${this._escapeHTML(line) || '<br>'}</p>`)\n .join('');\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n return;\n }\n\n // 3. Markdown paste — only when no HTML is on the clipboard (pure text source)\n if (this.options.markdownPaste !== false && !clipboardData.types.includes('text/html')) {\n const text = clipboardData.getData('text/plain');\n if (text && isMarkdown(text)) {\n event.preventDefault();\n const html = sanitiseHTML(markdownToHTML(text));\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n return;\n }\n }\n\n // 4. Sanitise HTML on paste when pasteCleanHTML is true (default)\n if (this.options.pasteCleanHTML !== false && clipboardData.types.includes('text/html')) {\n event.preventDefault();\n const raw = clipboardData.getData('text/html');\n // Detect source type and apply appropriate pre-cleaner\n const isWordContent = /<[a-z]+:[a-z]/i.test(raw) || /class=\"Mso/i.test(raw) || /\\bmso-/i.test(raw);\n const isSocialContent = /\\bdata-testid\\b/.test(raw) || /class=\"[^\"]*\\b(?:x[a-z0-9]{6,}|r-[a-z0-9]{3,})\\b/.test(raw);\n let html = raw;\n if (isWordContent) html = this._cleanWordHtml(html);\n else if (isSocialContent) html = this._cleanSocialHtml(html);\n html = sanitiseHTML(html);\n if (this.options.pasteStripAttributes) html = this._stripAttributes(html);\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n return;\n }\n\n // Otherwise let the browser handle paste natively\n }\n\n // ---------------------------------------------------------------------------\n // Drag & drop handlers\n // ---------------------------------------------------------------------------\n\n _onDragover(event) {\n if (!event.dataTransfer) return;\n const types = Array.from(event.dataTransfer.types || []);\n if (types.includes('Files')) {\n event.preventDefault();\n event.dataTransfer.dropEffect = 'copy';\n }\n }\n\n _onDrop(event) {\n const dt = event.dataTransfer;\n if (!dt || !dt.files || dt.files.length === 0) return;\n\n const imageFiles = Array.from(dt.files).filter((f) => f.type.startsWith('image/'));\n if (imageFiles.length === 0) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n // Place the caret at the drop coordinates before inserting\n this._placeCaretAtPoint(event.clientX, event.clientY);\n this._insertImageFiles(imageFiles);\n }\n\n // ---------------------------------------------------------------------------\n // Image file processing — shared by paste and drop\n // ---------------------------------------------------------------------------\n\n /**\n * Inserts one or more image Files into the editor.\n * Delegates to `options.onImageUpload` when provided; otherwise compresses\n * and embeds as base64.\n * @param {File[]} files\n */\n _insertImageFiles(files) {\n if (!files || files.length === 0) return;\n\n if (typeof this.options.onImageUpload === 'function') {\n this.options.onImageUpload(files);\n return;\n }\n\n // C2: Reject image formats that browsers cannot decode/display.\n const UNSUPPORTED = ['image/tiff', 'image/x-tiff', 'image/bmp', 'image/x-bmp', 'image/x-ms-bmp'];\n const maxBytes = (this.options.maxImageSize || 5) * 1024 * 1024;\n files.forEach((file) => {\n if (!file || !file.type.startsWith('image/')) return;\n if (UNSUPPORTED.includes(file.type)) {\n const message = `Image format \"${file.type}\" is not supported for display in web browsers. Please convert to PNG, JPEG, or WebP first.`;\n this.context.triggerEvent('imageError', { file, message });\n console.warn('[AutumnNote]', message);\n return;\n }\n if (file.size > maxBytes) {\n const message = `Image \"${file.name}\" exceeds the ${this.options.maxImageSize || 5} MB size limit.`;\n this.context.triggerEvent('imageError', { file, message });\n console.warn(`[AutumnNote] ${message}`);\n return;\n }\n\n const alt = file.name.replace(/\\.[^.]+$/, '');\n this._compressImage(file).then((dataUrl) => {\n // Keep the large data URL in a JS Map; insert a lightweight blob: URL\n // into the DOM so editable.innerHTML never contains the big base64 string.\n const blob = this._dataUrlToBlob(dataUrl);\n const blobUrl = URL.createObjectURL(blob);\n this._blobRegistry.set(blobUrl, dataUrl);\n this.context.invoke('editor.insertImage', blobUrl, alt);\n }).catch((err) => {\n const message = `Image \"${file.name}\" could not be processed.`;\n this.context.triggerEvent('imageError', { file, message, error: err });\n console.warn('[AutumnNote]', message, err);\n });\n });\n }\n\n /**\n * Replaces any blob: URLs created by this module with their original data URLs.\n * Called by Editor.getHTML() so the returned HTML is fully self-contained.\n * @param {string} html\n * @returns {string}\n */\n resolveImages(html) {\n if (!this._blobRegistry || !this._blobRegistry.size) return html;\n return html.replace(/blob:[^\"'> \\t\\n\\r]*/g, (url) => this._blobRegistry.get(url) || url);\n }\n\n /**\n * Converts a data URL to a Blob (no FileReader — synchronous).\n * @param {string} dataUrl\n * @returns {Blob}\n */\n _dataUrlToBlob(dataUrl) {\n const [header, b64] = dataUrl.split(',');\n const mime = header.match(/:(.*?);/)[1];\n const binary = atob(b64);\n const arr = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) arr[i] = binary.charCodeAt(i);\n return new Blob([arr], { type: mime });\n }\n\n /**\n * Compresses an image File using a Canvas.\n * - Resizes so the longest edge is at most MAX_DIM pixels.\n * - Encodes as WebP (if supported) or JPEG at quality 0.85.\n * Falls back to plain FileReader if canvas is unavailable.\n * @param {File} file\n * @returns {Promise<string>} data URL\n */\n _compressImage(file) {\n const MAX_DIM = 1920;\n const QUALITY = 0.85;\n\n return new Promise((resolve) => {\n const objectUrl = URL.createObjectURL(file);\n const img = new Image();\n\n img.onload = () => {\n URL.revokeObjectURL(objectUrl);\n\n let { width, height } = img;\n if (width > MAX_DIM || height > MAX_DIM) {\n if (width >= height) {\n height = Math.round((height * MAX_DIM) / width);\n width = MAX_DIM;\n } else {\n width = Math.round((width * MAX_DIM) / height);\n height = MAX_DIM;\n }\n }\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n // Canvas context unavailable (e.g. device memory limit) — fall back to\n // embedding the original file without compression.\n const reader = new FileReader();\n reader.onload = (e) => resolve(/** @type {string} */ (e.target.result));\n reader.readAsDataURL(file);\n return;\n }\n ctx.drawImage(img, 0, 0, width, height);\n\n // Prefer WebP for better compression; fall back to JPEG\n const webp = canvas.toDataURL('image/webp', QUALITY);\n resolve(webp.startsWith('data:image/webp') ? webp : canvas.toDataURL('image/jpeg', QUALITY));\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(objectUrl);\n // Fallback: embed original without compression\n const reader = new FileReader();\n reader.onload = (e) => resolve(/** @type {string} */ (e.target.result));\n reader.readAsDataURL(file);\n };\n\n img.src = objectUrl;\n });\n }\n\n /**\n * Positions the caret at the given viewport coordinates.\n * Supports both Chrome (caretRangeFromPoint) and Firefox (caretPositionFromPoint).\n * @param {number} x\n * @param {number} y\n */\n _placeCaretAtPoint(x, y) {\n let range;\n if (document.caretRangeFromPoint) {\n range = document.caretRangeFromPoint(x, y);\n } else if (document.caretPositionFromPoint) {\n const pos = document.caretPositionFromPoint(x, y);\n if (pos) {\n range = document.createRange();\n range.setStart(pos.offsetNode, pos.offset);\n range.collapse(true);\n }\n }\n if (!range) return;\n const sel = window.getSelection();\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Escapes HTML special characters.\n * @param {string} str\n * @returns {string}\n */\n _escapeHTML(str) {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n }\n}\n","/**\n * Placeholder.js - Shows placeholder text when the editor is empty\n * Inspired by Summernote's Placeholder module\n */\n\nimport { on } from '../core/dom.js';\n\nexport class Placeholder {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n }\n\n initialize() {\n const editable = this.context.layoutInfo.editable;\n const placeholder = this.options.placeholder || '';\n if (placeholder) {\n editable.dataset.placeholder = placeholder;\n }\n\n const update = () => this._update();\n const d1 = on(editable, 'input', update);\n const d2 = on(editable, 'focus', update);\n const d3 = on(editable, 'blur', update);\n this._disposers.push(d1, d2, d3);\n this._update();\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n }\n\n _update() {\n const editable = this.context.layoutInfo.editable;\n const isFocused = document.activeElement === editable;\n // Strip ZWS (\\u200B) cursor anchors used by checklist/icon insertion in\n // addition to regular whitespace before deciding if the editor is empty.\n // Without this, a freshly-created checklist item or icon leaves a ZWS in\n // the DOM that causes the placeholder to overlap real content (A-1).\n const hasText = editable.textContent.replace(/\\u200B/g, '').trim().length > 0;\n const isEmpty = !hasText &&\n !editable.querySelector('img, table, hr, .an-video-wrapper');\n editable.classList.toggle('an-placeholder', isEmpty && !isFocused);\n }\n}\n","/**\n * Codeview.js - HTML source code view / WYSIWYG toggle\n * Inspired by Summernote's Codeview module\n */\n\nimport { createElement } from '../core/dom.js';\nimport { sanitiseHTML } from '../core/sanitise.js';\n\nexport class Codeview {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._active = false;\n /** @type {HTMLTextAreaElement|null} */\n this._textarea = null;\n this._disposers = [];\n }\n\n initialize() {\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._textarea && this._textarea.parentNode) {\n this._textarea.parentNode.removeChild(this._textarea);\n }\n this._textarea = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n toggle() {\n if (this._active) {\n this.deactivate();\n } else {\n this.activate();\n }\n }\n\n isActive() {\n return this._active;\n }\n\n activate() {\n if (this._active) return;\n const { editable } = this.context.layoutInfo;\n const html = editable.innerHTML;\n\n this._textarea = createElement('textarea', {\n class: 'an-codeview',\n spellcheck: 'false',\n autocomplete: 'off',\n autocorrect: 'off',\n autocapitalize: 'off',\n });\n this._textarea.value = this._prettyPrint(html);\n\n editable.style.display = 'none';\n editable.parentNode.insertBefore(this._textarea, editable.nextSibling);\n\n this._active = true;\n this.context.invoke('toolbar.refresh');\n }\n\n deactivate() {\n if (!this._active || !this._textarea) return;\n const { editable } = this.context.layoutInfo;\n // Sanitise the HTML typed in the textarea before applying (allow iframes for video embeds)\n editable.innerHTML = sanitiseHTML(this._textarea.value, { allowIframes: true });\n this._textarea.parentNode.removeChild(this._textarea);\n this._textarea = null;\n editable.style.display = '';\n this._active = false;\n this.context.invoke('toolbar.refresh');\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Very simple HTML pretty-printer (indent nested tags).\n * Inline elements (a, span, strong, em, etc.) are kept on one line to\n * avoid injecting whitespace that would change rendered text.\n * @param {string} html\n * @returns {string}\n */\n _prettyPrint(html) {\n // Tags whose content must NOT be split with newlines (breaks text rendering)\n const INLINE_RE = /^<(a|abbr|b|bdo|br|button|cite|code|dfn|em|i|img|input|kbd|label|output|q|samp|select|small|span|strong|sub|sup|textarea|time|tt|u|var)([\\s>/])/i;\n let indent = 0;\n return html\n .replace(/>\\s*</g, (match, offset, str) => {\n // Check what comes after the '>' — if it starts an inline tag, keep on same line\n const remaining = str.slice(offset + 1);\n if (INLINE_RE.test(remaining.trimStart())) return '><';\n return '>\\n<';\n })\n .split('\\n')\n .map((line) => {\n const stripped = line.trim();\n if (!stripped) return '';\n if (/^<\\//.test(stripped)) indent = Math.max(0, indent - 1);\n const out = ' '.repeat(indent) + stripped;\n if (\n /^<[^/!][^>]*[^/]>/.test(stripped) &&\n !INLINE_RE.test(stripped) &&\n !/^<(br|hr|img|input|link|meta)/.test(stripped)\n ) {\n indent++;\n }\n return out;\n })\n .filter(Boolean)\n .join('\\n');\n }\n\n}\n\n","/**\n * Fullscreen.js - Toggles the editor in/out of fullscreen mode\n * Inspired by Summernote's Fullscreen module\n */\n\nimport { on } from '../core/dom.js';\nimport { key, isKey } from '../core/key.js';\n\nexport class Fullscreen {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this._active = false;\n this._disposers = [];\n /** @type {string} cached editable height before fullscreen */\n this._prevHeight = '';\n }\n\n initialize() {\n // Press Escape to exit fullscreen\n const d = on(document, 'keydown', (event) => {\n if (this._active && isKey(event, key.ESCAPE)) {\n this.deactivate();\n }\n });\n this._disposers.push(d);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._active) this.deactivate();\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n toggle() {\n if (this._active) {\n this.deactivate();\n } else {\n this.activate();\n }\n }\n\n isActive() {\n return this._active;\n }\n\n activate() {\n if (this._active) return;\n const container = this.context.layoutInfo.container;\n // Save the container's explicit height (set by the resize handle) so it\n // can be restored when exiting fullscreen.\n this._prevHeight = container.style.height;\n\n container.classList.add('an-fullscreen');\n // Clear any resize-imposed height so the fullscreen CSS (inset:0) takes over.\n container.style.height = '';\n document.body.style.overflow = 'hidden';\n this._active = true;\n this.context.invoke('toolbar.refresh');\n }\n\n deactivate() {\n if (!this._active) return;\n const container = this.context.layoutInfo.container;\n\n container.classList.remove('an-fullscreen');\n // Restore whatever explicit height the user had set via the resize handle.\n container.style.height = this._prevHeight;\n document.body.style.overflow = '';\n this._active = false;\n this.context.invoke('toolbar.refresh');\n }\n}\n","/**\n * LinkDialog.js - Dialog for inserting / editing hyperlinks\n * Inspired by Summernote's LinkDialog — rewritten without jQuery\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\nexport class LinkDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the link dialog.\n * Pre-fills with the currently selected link if present.\n */\n show() {\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._prefill();\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.linkDialog;\n const overlay = createElement('div', { class: 'an-dialog-overlay', role: 'dialog', 'aria-modal': 'true', 'aria-label': L.ariaLabel });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n\n // URL field\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.url;\n const urlInput = createElement('input', {\n type: 'url',\n class: 'an-input',\n placeholder: L.urlPlaceholder,\n id: 'an-link-url',\n name: 'url',\n autocomplete: 'off',\n });\n this._urlInput = urlInput;\n\n // Text field\n const textLabel = createElement('label', { class: 'an-label' });\n textLabel.textContent = L.displayText;\n const textInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.textPlaceholder,\n id: 'an-link-text',\n name: 'linkText',\n autocomplete: 'off',\n });\n this._textInput = textInput;\n\n // Open in new tab\n const tabLabel = createElement('label', { class: 'an-label an-label-inline' });\n const tabCheckbox = createElement('input', {\n type: 'checkbox',\n id: 'an-link-newtab',\n name: 'openInNewTab',\n });\n this._tabCheckbox = tabCheckbox;\n tabLabel.appendChild(tabCheckbox);\n tabLabel.appendChild(document.createTextNode(' ' + L.openInNewTab));\n\n // Buttons\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n box.append(title, urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);\n overlay.appendChild(box);\n\n // Events\n const d1 = on(insertBtn, 'click', () => this._onInsert());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(urlInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(textInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d1, d2, d3, d4, d5);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _prefill() {\n // Try to find currently selected anchor\n const sel = window.getSelection();\n let anchor = null;\n if (sel && sel.rangeCount > 0) {\n let node = sel.getRangeAt(0).startContainer;\n while (node) {\n if (node.nodeName === 'A') { anchor = node; break; }\n node = node.parentNode;\n }\n }\n if (anchor) {\n this._urlInput.value = anchor.getAttribute('href') || '';\n this._textInput.value = anchor.textContent || '';\n this._tabCheckbox.checked = anchor.getAttribute('target') === '_blank';\n } else {\n this._urlInput.value = '';\n this._textInput.value = sel ? sel.toString() : '';\n this._tabCheckbox.checked = false;\n }\n }\n\n _onInsert() {\n let url = this._urlInput.value.trim();\n const text = this._textInput.value.trim();\n const newTab = this._tabCheckbox.checked;\n\n if (!url) {\n this._urlInput.focus();\n return;\n }\n\n // Auto-prefix with https:// if no protocol is present\n if (!/^[a-zA-Z][a-zA-Z\\d+\\-.]*:/.test(url)) {\n url = 'https://' + url;\n }\n\n // Block unsafe protocols\n try {\n const parsed = new URL(url);\n if (/^javascript:/i.test(parsed.protocol) || /^vbscript:/i.test(parsed.protocol) || /^data:/i.test(parsed.protocol)) {\n this._urlInput.focus();\n return;\n }\n } catch {\n // URL constructor failed — not a valid URL\n this._urlInput.focus();\n return;\n }\n\n // Restore selection then insert\n if (this._savedRange) {\n this._savedRange.select();\n }\n\n this.context.invoke('editor.insertLink', url, text, newTab);\n this._close();\n }\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._urlInput && this._urlInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n}\n","/**\n * ImageDialog.js - Dialog for inserting images (by URL or file upload)\n * Inspired by Summernote's ImageDialog — rewritten without jQuery\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\nexport class ImageDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._urlInput.value = '';\n this._altInput.value = '';\n if (this._fileInput) this._fileInput.value = '';\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.imageDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n\n // URL tab\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.imageUrl;\n const urlInput = createElement('input', {\n type: 'url',\n class: 'an-input',\n placeholder: L.urlPlaceholder,\n autocomplete: 'off',\n });\n this._urlInput = urlInput;\n\n // Alt text\n const altLabel = createElement('label', { class: 'an-label' });\n altLabel.textContent = L.altText;\n const altInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.altPlaceholder,\n autocomplete: 'off',\n });\n this._altInput = altInput;\n\n box.append(title, urlLabel, urlInput, altLabel, altInput);\n\n // Alignment\n const alignLabel = createElement('label', { class: 'an-label' });\n alignLabel.textContent = L.alignment;\n const alignRow = createElement('div', { class: 'an-align-row' });\n const alignOptions = [\n { value: '', label: L.alignNone },\n { value: 'left', label: L.alignLeft },\n { value: 'center', label: L.alignCenter },\n { value: 'right', label: L.alignRight },\n ];\n alignOptions.forEach(({ value, label }) => {\n const radioId = `an-align-${value || 'none'}`;\n const radio = createElement('input', { type: 'radio', name: 'an-img-align', id: radioId, value });\n if (value === '') radio.checked = true;\n const lbl = createElement('label', { for: radioId, class: 'an-align-label' });\n lbl.textContent = label;\n alignRow.append(radio, lbl);\n });\n this._alignRow = alignRow;\n box.append(alignLabel, alignRow);\n if (this.options.allowImageUpload !== false) {\n const fileLabel = createElement('label', { class: 'an-label' });\n fileLabel.textContent = L.uploadLabel;\n const fileInput = createElement('input', {\n type: 'file',\n class: 'an-input',\n accept: 'image/jpeg,image/png,image/gif,image/webp,image/svg+xml,image/avif',\n });\n this._fileInput = fileInput;\n // Hint line shown below the file input for format errors\n const fileHint = createElement('p', { class: 'an-dialog-hint' });\n this._fileHint = fileHint;\n const d = on(fileInput, 'change', () => this._onFileChange());\n this._disposers.push(d);\n box.append(fileLabel, fileInput, fileHint);\n }\n\n // Buttons\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n box.append(btnRow);\n overlay.appendChild(box);\n\n const d1 = on(insertBtn, 'click', () => this._onInsert());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(urlInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(altInput, 'keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d1, d2, d3, d4, d5);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _onFileChange() {\n const file = this._fileInput && this._fileInput.files && this._fileInput.files[0];\n if (!file || !file.type.startsWith('image/')) return;\n\n // C2: Only allow web-displayable formats. TIFF, BMP, RAW and similar\n // formats are not rendered by browsers — reject them with a clear message.\n const SUPPORTED = new Set([\n 'image/jpeg', 'image/png', 'image/gif',\n 'image/webp', 'image/svg+xml', 'image/avif',\n ]);\n if (!SUPPORTED.has(file.type)) {\n const message = this.context.locale.errors.imageFormat(file.type);\n if (this._fileHint) this._fileHint.textContent = message;\n this.context.triggerEvent('imageError', { file, message });\n this._fileInput.value = '';\n return;\n }\n if (this._fileHint) this._fileHint.textContent = '';\n\n // Validate file size (max 5 MB by default)\n const maxSize = (this.options.maxImageSize || 5) * 1024 * 1024;\n if (file.size > maxSize) {\n const message = this.context.locale.errors.imageSize(this.options.maxImageSize || 5);\n if (this._fileHint) this._fileHint.textContent = message;\n console.warn('[AutumnNote] ImageDialog:', message);\n this.context.triggerEvent('imageError', { file, message });\n this._fileInput.value = '';\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (e) => {\n this._urlInput.value = /** @type {string} */ (e.target.result);\n };\n reader.readAsDataURL(file);\n }\n\n _onInsert() {\n const src = this._urlInput.value.trim();\n const alt = this._altInput.value.trim();\n const alignRadio = this._alignRow && this._alignRow.querySelector('input[name=\"an-img-align\"]:checked');\n const align = alignRadio ? alignRadio.value : '';\n\n if (!src) {\n this._urlInput.focus();\n return;\n }\n\n if (this._savedRange) {\n this._savedRange.select();\n }\n\n this.context.invoke('editor.insertImage', src, alt, align);\n this._close();\n }\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._urlInput && this._urlInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n}\n","/**\n * VideoDialog.js - Dialog for inserting videos (YouTube, Vimeo, or direct file)\n * Supports:\n * • YouTube watch URLs → <iframe> embed\n * • YouTube short URLs → <iframe> embed\n * • Vimeo URLs → <iframe> embed\n * • Direct video URLs → <video> element (.mp4 / .webm / .ogg)\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\nexport class VideoDialog {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._urlInput.value = '';\n this._widthInput.value = '560';\n this._hintEl.textContent = '';\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.videoDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n\n // URL input\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.videoUrl;\n const urlInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'url',\n class: 'an-input',\n placeholder: L.urlPlaceholder,\n autocomplete: 'off',\n }));\n this._urlInput = urlInput;\n\n // Hint (detected source)\n const hintEl = createElement('p', { class: 'an-dialog-hint' });\n this._hintEl = hintEl;\n\n // Width\n const widthLabel = createElement('label', { class: 'an-label' });\n widthLabel.textContent = L.widthLabel;\n const widthInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'number',\n class: 'an-input',\n placeholder: '560',\n min: '80',\n max: '1920',\n value: '560',\n }));\n this._widthInput = widthInput;\n\n // Buttons\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n box.append(title, urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);\n overlay.appendChild(box);\n\n // Live URL hint\n const d0 = on(urlInput, 'input', () => {\n const info = this._parseVideoUrl(urlInput.value.trim());\n hintEl.textContent = info ? this.context.locale.videoDialog.detected(info.type) : (urlInput.value ? this.context.locale.videoDialog.unknownFormat : '');\n });\n\n const d1 = on(insertBtn, 'click', () => this._onInsert());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d0, d1, d2, d3, d4);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _onInsert() {\n const rawUrl = this._urlInput.value.trim();\n const width = Math.max(80, parseInt(this._widthInput.value, 10) || 560);\n\n if (!rawUrl) {\n this._urlInput.focus();\n return;\n }\n\n const html = this._buildEmbedHtml(rawUrl, width);\n if (!html) {\n this._hintEl.textContent = this.context.locale.videoDialog.invalidUrl;\n this._urlInput.focus();\n return;\n }\n\n if (this._savedRange) this._savedRange.select();\n this.context.invoke('editor.insertVideo', html);\n this._close();\n }\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._urlInput && this._urlInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n\n // ---------------------------------------------------------------------------\n // URL parsing & HTML building\n // ---------------------------------------------------------------------------\n\n /**\n * Parses a video URL and returns { type, embedUrl } or null.\n * @param {string} url\n * @returns {{ type: string, embedUrl: string }|null}\n */\n _parseVideoUrl(url) {\n if (!url) return null;\n\n // Validate — block javascript: and other dangerous protocols\n try {\n const parsed = new URL(url);\n if (/^javascript:/i.test(parsed.protocol) || /^vbscript:/i.test(parsed.protocol)) return null;\n } catch { return null; }\n\n // YouTube watch: https://www.youtube.com/watch?v=ID\n const ytWatch = url.match(/(?:youtube\\.com\\/watch\\?(?:.*&)?v=|youtube\\.com\\/embed\\/)([a-zA-Z0-9_-]{11})/);\n if (ytWatch) return { type: 'YouTube', embedUrl: `https://www.youtube.com/embed/${ytWatch[1]}` };\n\n // YouTube short: https://youtu.be/ID\n const ytShort = url.match(/youtu\\.be\\/([a-zA-Z0-9_-]{11})/);\n if (ytShort) return { type: 'YouTube', embedUrl: `https://www.youtube.com/embed/${ytShort[1]}` };\n\n // YouTube Shorts: https://www.youtube.com/shorts/ID\n const ytShorts = url.match(/youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]{11})/);\n if (ytShorts) return { type: 'YouTube Shorts', embedUrl: `https://www.youtube.com/embed/${ytShorts[1]}` };\n\n // Vimeo: https://vimeo.com/ID\n const vimeo = url.match(/vimeo\\.com\\/(\\d+)/);\n if (vimeo) return { type: 'Vimeo', embedUrl: `https://player.vimeo.com/video/${vimeo[1]}` };\n\n // Direct video file\n if (/\\.(mp4|webm|ogg|ogv|mov)(#.*|\\?.*)?$/i.test(url)) {\n return { type: 'Direct video', embedUrl: url };\n }\n\n return null;\n }\n\n /**\n * Builds the HTML string to insert.\n * @param {string} url\n * @param {number} width\n * @returns {string|null}\n */\n _buildEmbedHtml(url, width) {\n const info = this._parseVideoUrl(url);\n const height = Math.round(width * 9 / 16); // 16:9\n\n if (info && (info.type === 'YouTube' || info.type === 'YouTube Shorts' || info.type === 'Vimeo')) {\n const iframeTitle = `${info.type} video player`;\n return (\n `<div class=\"an-video-wrapper\" style=\"position:relative;display:block;width:${width}px;max-width:100%\">` +\n `<iframe src=\"${info.embedUrl}\" width=\"${width}\" height=\"${height}\" ` +\n `title=\"${iframeTitle}\" ` +\n `frameborder=\"0\" allowfullscreen ` +\n `allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" ` +\n `style=\"display:block;max-width:100%\"></iframe>` +\n `<div class=\"an-video-shield\"></div>` +\n `</div>`\n );\n }\n\n if (info && info.type === 'Direct video') {\n const src = info.embedUrl.replace(/\"/g, '%22');\n return (\n `<div class=\"an-video-wrapper\" style=\"position:relative;display:block;width:${width}px;max-width:100%\">` +\n `<video src=\"${src}\" width=\"${width}\" height=\"${height}\" controls ` +\n `style=\"display:block;max-width:100%\"></video>` +\n `<div class=\"an-video-shield\"></div>` +\n `</div>`\n );\n }\n\n // Unknown URL — let the user try as a direct video\n const safeSrc = (() => {\n try {\n const p = new URL(url);\n if (/^javascript:/i.test(p.protocol) || /^vbscript:/i.test(p.protocol)) return null;\n return url;\n } catch { return null; }\n })();\n if (!safeSrc) return null;\n\n const escapedSrc = safeSrc.replace(/\"/g, '%22');\n return (\n `<div class=\"an-video-wrapper\" style=\"position:relative;display:block;width:${width}px;max-width:100%\">` +\n `<video src=\"${escapedSrc}\" width=\"${width}\" height=\"${height}\" controls ` +\n `style=\"display:block;max-width:100%\"></video>` +\n `<div class=\"an-video-shield\"></div>` +\n `</div>`\n );\n }\n}\n","// ImageResizer.js - Interactive resize handles for selected images in the editor\nimport { on } from '../core/dom.js';\n\n/**\n * Eight handle positions. 'pos' is used as CSS class suffix and\n * to determine which axis/direction is being dragged.\n *\n * Pos length 2 → corner handle → maintain aspect ratio.\n * Pos length 1 → edge handle → single-axis resize.\n */\nconst HANDLE_DEFS = [\n { pos: 'nw', cursor: 'nw-resize' },\n { pos: 'n', cursor: 'n-resize' },\n { pos: 'ne', cursor: 'ne-resize' },\n { pos: 'e', cursor: 'e-resize' },\n { pos: 'se', cursor: 'se-resize' },\n { pos: 's', cursor: 's-resize' },\n { pos: 'sw', cursor: 'sw-resize' },\n { pos: 'w', cursor: 'w-resize' },\n];\n\nexport class ImageResizer {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLImageElement|null} */\n this._activeImg = null;\n this._overlay = null;\n this._disposers = [];\n this._positionRaf = null;\n }\n\n initialize() {\n this._overlay = this._buildOverlay();\n const container = this.context.layoutInfo.editable.closest('.an-container') || document.body;\n container.appendChild(this._overlay);\n this._container = container;\n\n const editable = this.context.layoutInfo.editable;\n\n // Debounce window resize — _updateOverlayPosition already has rAF gating but\n // every call cancels + re-schedules it; a debounce reduces that churn.\n let _resizeDebounce = null;\n const onWindowResize = () => {\n clearTimeout(_resizeDebounce);\n _resizeDebounce = setTimeout(() => this._updateOverlayPosition(), 100);\n };\n\n this._disposers.push(\n on(editable, 'click', (e) => this._onEditorClick(e)),\n // Also select on right-click so the highlight shows before the context menu\n on(editable, 'contextmenu', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const img = e.target.closest('img');\n if (img) this._select(img);\n }),\n on(document, 'click', (e) => this._onDocClick(e)),\n on(window, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n on(window, 'resize', onWindowResize, { passive: true }),\n on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n );\n\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dragDisposers) {\n this._dragDisposers.forEach((d) => d());\n this._dragDisposers = null;\n }\n if (this._positionRaf) {\n cancelAnimationFrame(this._positionRaf);\n this._positionRaf = null;\n }\n this._deselect();\n if (this._overlay && this._overlay.parentNode) {\n this._overlay.parentNode.removeChild(this._overlay);\n }\n this._overlay = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLImageElement|null} */\n getActiveImage() {\n return this._activeImg;\n }\n\n /** Re-sync overlay position (call after external size changes). */\n updateOverlay() {\n this._updateOverlayPosition();\n }\n\n /** Programmatically clear the current image selection. */\n deselect() {\n this._deselect();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n _buildOverlay() {\n const overlay = document.createElement('div');\n overlay.className = 'an-image-resizer';\n overlay.style.display = 'none';\n\n HANDLE_DEFS.forEach(({ pos }) => {\n const h = document.createElement('div');\n h.className = `an-resize-handle an-resize-${pos}`;\n h.dataset.handle = pos;\n // Attach handle listeners here so they're torn down in destroy() via _disposers\n this._disposers.push(\n on(h, 'mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startResize(e, pos);\n }),\n );\n overlay.appendChild(h);\n });\n\n return overlay;\n }\n\n _onEditorClick(e) {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const img = e.target.closest('img');\n if (img) {\n // Prevent browser from deselecting the current text selection / opening native resize\n e.preventDefault();\n this._select(img);\n }\n }\n\n _onDocClick(e) {\n if (!this._activeImg) return;\n if (e.target === this._activeImg) return;\n if (this._overlay && this._overlay.contains(e.target)) return;\n // Don't deselect while interacting with the context menu\n if (e.target.closest('.an-contextmenu')) return;\n this._deselect();\n }\n\n _select(img) {\n if (this._activeImg && this._activeImg !== img) {\n this._activeImg.classList.remove('an-image-selected');\n }\n this._activeImg = img;\n img.classList.add('an-image-selected');\n this._updateOverlayPosition();\n this._overlay.style.display = 'block';\n }\n\n _deselect() {\n if (this._activeImg) {\n this._activeImg.classList.remove('an-image-selected');\n this._activeImg = null;\n }\n if (this._overlay) this._overlay.style.display = 'none';\n }\n\n _updateOverlayPosition() {\n if (this._positionRaf) cancelAnimationFrame(this._positionRaf);\n this._positionRaf = requestAnimationFrame(() => {\n this._positionRaf = null;\n this._updateOverlayPositionNow();\n });\n }\n\n _updateOverlayPositionNow() {\n if (!this._activeImg || !this._overlay) return;\n const offsetParent = this._overlay.offsetParent || this._container;\n const containerRect = offsetParent.getBoundingClientRect();\n const rect = this._activeImg.getBoundingClientRect();\n const left = rect.left - containerRect.left + offsetParent.scrollLeft;\n const top = rect.top - containerRect.top + offsetParent.scrollTop;\n this._overlay.style.left = `${left}px`;\n this._overlay.style.top = `${top}px`;\n this._overlay.style.width = `${rect.width}px`;\n this._overlay.style.height = `${rect.height}px`;\n }\n\n _startResize(e, pos) {\n const img = this._activeImg;\n if (!img) return;\n\n const startX = e.clientX;\n const startY = e.clientY;\n const startW = img.offsetWidth || img.naturalWidth || 100;\n const startH = img.offsetHeight || img.naturalHeight || 100;\n const aspectRatio = startW / (startH || 1);\n const isCorner = pos.length === 2; // 'nw','ne','se','sw'\n\n const editable = this.context.layoutInfo.editable;\n let _raf = null; // rAF handle — ensures at most one write per paint frame\n\n const onMove = (me) => {\n if (_raf !== null) return; // frame already pending, discard this event\n const clientX = me.clientX;\n const clientY = me.clientY;\n _raf = requestAnimationFrame(() => {\n _raf = null;\n const dx = clientX - startX;\n const dy = clientY - startY;\n const maxW = editable.clientWidth || Infinity;\n let newW = startW;\n let newH = startH;\n\n if (pos.includes('e')) newW = Math.max(20, startW + dx);\n if (pos.includes('w')) newW = Math.max(20, startW - dx);\n if (pos.includes('s')) newH = Math.max(20, startH + dy);\n if (pos.includes('n')) newH = Math.max(20, startH - dy);\n\n newW = Math.min(newW, maxW);\n\n if (isCorner) {\n if (Math.abs(dx) >= Math.abs(dy)) {\n newH = Math.max(20, Math.round(newW / aspectRatio));\n } else {\n newW = Math.min(Math.max(20, Math.round(newH * aspectRatio)), maxW);\n newH = Math.max(20, Math.round(newW / aspectRatio));\n }\n }\n\n img.style.width = `${newW}px`;\n img.style.height = `${newH}px`;\n this._updateOverlayPosition();\n });\n };\n\n const onUp = () => {\n if (_raf !== null) { cancelAnimationFrame(_raf); _raf = null; }\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this._dragDisposers = null;\n this.context.invoke('editor.afterCommand');\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n // Track these so destroy() can clean them up if called during an active drag\n this._dragDisposers = [\n () => document.removeEventListener('mousemove', onMove),\n () => document.removeEventListener('mouseup', onUp),\n ];\n }\n}\n","// VideoResizer.js - Interactive resize handles for selected videos in the editor\n// Targets .an-video-wrapper divs (containing <iframe> or <video>)\nimport { on } from '../core/dom.js';\n\nconst HANDLE_DEFS = [\n { pos: 'nw', cursor: 'nw-resize' },\n { pos: 'n', cursor: 'n-resize' },\n { pos: 'ne', cursor: 'ne-resize' },\n { pos: 'e', cursor: 'e-resize' },\n { pos: 'se', cursor: 'se-resize' },\n { pos: 's', cursor: 's-resize' },\n { pos: 'sw', cursor: 'sw-resize' },\n { pos: 'w', cursor: 'w-resize' },\n];\n\nexport class VideoResizer {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} — the .an-video-wrapper div */\n this._activeWrapper = null;\n this._overlay = null;\n this._disposers = [];\n this._positionRaf = null;\n }\n\n initialize() {\n this._overlay = this._buildOverlay();\n const container = this.context.layoutInfo.editable.closest('.an-container') || document.body;\n container.appendChild(this._overlay);\n this._container = container;\n\n const editable = this.context.layoutInfo.editable;\n\n let _resizeDebounce = null;\n const onWindowResize = () => {\n clearTimeout(_resizeDebounce);\n _resizeDebounce = setTimeout(() => this._updateOverlayPosition(), 100);\n };\n\n this._disposers.push(\n on(editable, 'click', (e) => this._onEditorClick(e)),\n on(editable, 'contextmenu', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const wrapper = this._findWrapper(e.target);\n if (wrapper) this._select(wrapper);\n }),\n on(document, 'click', (e) => this._onDocClick(e)),\n on(window, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n on(window, 'resize', onWindowResize),\n on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n // D1: Prevent native browser drag of video wrappers. Without this, a user\n // can hold-and-drag to produce a \"copy\" that lands outside .an-editable,\n // where the .an-video-shield CSS loses its containing context so the\n // copied video becomes directly playable.\n on(editable, 'dragstart', (e) => {\n if (e.target instanceof Element && e.target.closest('.an-video-wrapper')) {\n e.preventDefault();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dragDisposers) {\n this._dragDisposers.forEach((d) => d());\n this._dragDisposers = null;\n }\n if (this._positionRaf) {\n cancelAnimationFrame(this._positionRaf);\n this._positionRaf = null;\n }\n this._deselect();\n if (this._overlay && this._overlay.parentNode) {\n this._overlay.parentNode.removeChild(this._overlay);\n }\n this._overlay = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLElement|null} */\n getActiveWrapper() {\n return this._activeWrapper;\n }\n\n updateOverlay() {\n this._updateOverlayPosition();\n }\n\n deselect() {\n this._deselect();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n /**\n * Walk up the DOM from `el` to find the nearest .an-video-wrapper,\n * or an iframe/video whose parent is .an-video-wrapper.\n * @param {EventTarget} el\n * @returns {HTMLElement|null}\n */\n _findWrapper(el) {\n if (!el || !(el instanceof Element)) return null;\n // Direct hit on wrapper\n if (el.classList && el.classList.contains('an-video-wrapper')) return el;\n // Child element (iframe, video, or nested)\n const w = el.closest('.an-video-wrapper');\n if (w) return w;\n return null;\n }\n\n _buildOverlay() {\n const overlay = document.createElement('div');\n overlay.className = 'an-video-resizer';\n overlay.style.display = 'none';\n\n HANDLE_DEFS.forEach(({ pos }) => {\n const h = document.createElement('div');\n h.className = `an-resize-handle an-resize-${pos}`;\n h.dataset.handle = pos;\n this._disposers.push(\n on(h, 'mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startResize(e, pos);\n }),\n );\n overlay.appendChild(h);\n });\n\n return overlay;\n }\n\n _onEditorClick(e) {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const wrapper = this._findWrapper(e.target);\n if (wrapper) {\n e.preventDefault();\n this._select(wrapper);\n }\n }\n\n _onDocClick(e) {\n if (!this._activeWrapper) return;\n if (this._activeWrapper.contains(e.target)) return;\n if (this._overlay && this._overlay.contains(e.target)) return;\n if (e.target.closest('.an-contextmenu')) return;\n this._deselect();\n }\n\n _select(wrapper) {\n if (this._activeWrapper && this._activeWrapper !== wrapper) {\n this._activeWrapper.classList.remove('an-video-selected');\n }\n this._activeWrapper = wrapper;\n wrapper.classList.add('an-video-selected');\n this._updateOverlayPosition();\n this._overlay.style.display = 'block';\n }\n\n _deselect() {\n if (this._activeWrapper) {\n this._activeWrapper.classList.remove('an-video-selected');\n this._activeWrapper = null;\n }\n if (this._overlay) this._overlay.style.display = 'none';\n }\n\n _updateOverlayPosition() {\n if (this._positionRaf) cancelAnimationFrame(this._positionRaf);\n this._positionRaf = requestAnimationFrame(() => {\n this._positionRaf = null;\n this._updateOverlayPositionNow();\n });\n }\n\n _updateOverlayPositionNow() {\n if (!this._activeWrapper || !this._overlay) return;\n const offsetParent = this._overlay.offsetParent || this._container;\n const containerRect = offsetParent.getBoundingClientRect();\n const rect = this._activeWrapper.getBoundingClientRect();\n const left = rect.left - containerRect.left + offsetParent.scrollLeft;\n const top = rect.top - containerRect.top + offsetParent.scrollTop;\n this._overlay.style.left = `${left}px`;\n this._overlay.style.top = `${top}px`;\n this._overlay.style.width = `${rect.width}px`;\n this._overlay.style.height = `${rect.height}px`;\n }\n\n _startResize(e, pos) {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n\n const embed = wrapper.querySelector('iframe, video');\n const startX = e.clientX;\n const startY = e.clientY;\n const startW = wrapper.offsetWidth || 560;\n const startH = wrapper.offsetHeight || 315;\n const aspectRatio = startW / (startH || 1);\n const isCorner = pos.length === 2;\n\n const editable = this.context.layoutInfo.editable;\n let _raf = null; // rAF handle — at most one write per paint frame\n\n const onMove = (me) => {\n if (_raf !== null) return;\n const clientX = me.clientX;\n const clientY = me.clientY;\n _raf = requestAnimationFrame(() => {\n _raf = null;\n const dx = clientX - startX;\n const dy = clientY - startY;\n const maxW = editable.clientWidth || Infinity;\n let newW = startW;\n let newH = startH;\n\n if (pos.includes('e')) newW = Math.max(80, startW + dx);\n if (pos.includes('w')) newW = Math.max(80, startW - dx);\n if (pos.includes('s')) newH = Math.max(45, startH + dy);\n if (pos.includes('n')) newH = Math.max(45, startH - dy);\n\n newW = Math.min(newW, maxW);\n\n if (isCorner) {\n if (Math.abs(dx) >= Math.abs(dy)) {\n newH = Math.max(45, Math.round(newW / aspectRatio));\n } else {\n newW = Math.min(Math.max(80, Math.round(newH * aspectRatio)), maxW);\n newH = Math.max(45, Math.round(newW / aspectRatio));\n }\n }\n\n // Resize wrapper and inner embed via CSS only — attribute writes are redundant\n wrapper.style.width = `${newW}px`;\n wrapper.style.height = `${newH}px`;\n if (embed) {\n embed.style.width = `${newW}px`;\n embed.style.height = `${newH}px`;\n }\n this._updateOverlayPosition();\n });\n };\n\n const onUp = () => {\n if (_raf !== null) { cancelAnimationFrame(_raf); _raf = null; }\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this._dragDisposers = null;\n this.context.invoke('editor.afterCommand');\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n // Track these so destroy() can clean them up if called during an active drag\n this._dragDisposers = [\n () => document.removeEventListener('mousemove', onMove),\n () => document.removeEventListener('mouseup', onUp),\n ];\n }\n}\n","// LinkTooltip.js - Hover tooltip for links inside the editor\n// Displays a small action bar with: visit link, edit link, unlink\nimport { createElement, on } from '../core/dom.js';\n\nconst ICONS = {\n open: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/></svg>`,\n edit: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`,\n unlink: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18.84 12.25l1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71\"/><path d=\"M5.17 11.75l-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71\"/><line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"5\"/><line x1=\"2\" y1=\"8\" x2=\"5\" y2=\"8\"/><line x1=\"16\" y1=\"19\" x2=\"16\" y2=\"22\"/><line x1=\"19\" y1=\"16\" x2=\"22\" y2=\"16\"/></svg>`,\n copy: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`,\n};\n\n/** Delay in ms before showing / after hiding to avoid flicker */\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 200;\n\nexport class LinkTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeAnchor = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n // Detect when pointer enters a link\n on(editable, 'mouseover', (e) => {\n const anchor = e.target.closest('a[href]');\n if (anchor && editable.contains(anchor)) {\n this._scheduleShow(anchor);\n }\n }),\n // Detect when pointer leaves the editable area entirely\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.link;\n const el = createElement('div', { class: 'an-link-tooltip', role: 'toolbar', 'aria-label': L.ariaLabel });\n el.style.display = 'none';\n\n // URL preview text (truncated)\n this._urlLabel = createElement('span', { class: 'an-link-tooltip-url' });\n el.appendChild(this._urlLabel);\n\n // Separator\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n // Action buttons\n this._openBtn = this._makeBtn(ICONS.open, L.openLink, () => this._openLink());\n this._copyBtn = this._makeBtn(ICONS.copy, L.copyUrl, () => this._copyLink());\n this._editBtn = this._makeBtn(ICONS.edit, L.editLink, () => this._editLink());\n this._unlinkBtn = this._makeBtn(ICONS.unlink, L.removeLink, () => this._unlink());\n\n el.appendChild(this._openBtn);\n el.appendChild(this._copyBtn);\n el.appendChild(this._editBtn);\n el.appendChild(this._unlinkBtn);\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n _makeBtn(icon, title, handler) {\n const btn = createElement('button', { type: 'button', class: 'an-link-tooltip-btn', title });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => { e.preventDefault(); e.stopPropagation(); handler(); }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide logic\n // ---------------------------------------------------------------------------\n\n _scheduleShow(anchor) {\n if (this._activeAnchor === anchor && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeAnchor = anchor;\n this._show(anchor);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n if (this._hideTimer) return;\n this._hideTimer = setTimeout(() => {\n this._hide();\n }, HIDE_DELAY);\n }\n\n _show(anchor) {\n const isReadOnly = this.context.layoutInfo.container.classList.contains('an-disabled');\n const url = anchor.getAttribute('href') || '';\n this._urlLabel.textContent = this._truncateUrl(url);\n this._urlLabel.title = url;\n // In read-only mode keep only open + copy; hide edit and unlink\n this._editBtn.style.display = isReadOnly ? 'none' : '';\n this._unlinkBtn.style.display = isReadOnly ? 'none' : '';\n this._el.style.display = 'flex';\n this._positionNear(anchor);\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activeAnchor = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(anchor) {\n const rect = anchor.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 260;\n const tipH = this._el.offsetHeight || 34;\n const margin = 6;\n\n // Prefer below the link; if no room, put above\n let top = rect.bottom + margin;\n let left = rect.left;\n\n if (top + tipH > window.innerHeight - margin) {\n top = rect.top - tipH - margin;\n }\n if (left + tipW > window.innerWidth - margin) {\n left = window.innerWidth - tipW - margin;\n }\n if (left < margin) left = margin;\n\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n _truncateUrl(url) {\n try {\n const u = new URL(url);\n const display = u.host + (u.pathname !== '/' ? u.pathname : '');\n return display.length > 48 ? display.slice(0, 48) + '…' : display;\n } catch {\n return url.length > 48 ? url.slice(0, 48) + '…' : url;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _openLink() {\n const url = this._activeAnchor && this._activeAnchor.getAttribute('href');\n if (url) window.open(url, '_blank', 'noopener,noreferrer');\n this._hide();\n }\n\n _copyLink() {\n const url = this._activeAnchor && this._activeAnchor.getAttribute('href');\n if (url) {\n navigator.clipboard.writeText(url).catch(() => {\n // Fallback for environments where clipboard API is unavailable\n const ta = document.createElement('textarea');\n ta.value = url;\n ta.style.position = 'fixed';\n ta.style.opacity = '0';\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n });\n }\n // Brief visual feedback \n if (this._copyBtn) {\n this._copyBtn.classList.add('an-link-tooltip-btn--copied');\n setTimeout(() => this._copyBtn && this._copyBtn.classList.remove('an-link-tooltip-btn--copied'), 1000);\n }\n }\n\n _editLink() {\n const anchor = this._activeAnchor;\n if (!anchor) return;\n this._hide();\n\n // Place cursor inside the anchor, then open the link dialog (which pre-fills from selection)\n const sel = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(anchor);\n sel.removeAllRanges();\n sel.addRange(range);\n\n this.context.invoke('linkDialog.show');\n }\n\n _unlink() {\n const anchor = this._activeAnchor;\n if (!anchor) return;\n this._hide();\n\n // Select the anchor text, then remove the link\n const sel = window.getSelection();\n const range = document.createRange();\n range.selectNode(anchor);\n sel.removeAllRanges();\n sel.addRange(range);\n\n document.execCommand('unlink');\n this.context.invoke('editor.afterCommand');\n }\n}\n","// ImageTooltip.js - Hover tooltip for images inside the editor\n// Displays a horizontal action bar below (or above) the selected image,\n// similar in appearance and interaction to LinkTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst ICONS = {\n floatLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"6\" x2=\"22\" y2=\"6\"/><line x1=\"12\" y1=\"9\" x2=\"22\" y2=\"9\"/><line x1=\"12\" y1=\"12\" x2=\"22\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"14\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"2\" y1=\"6\" x2=\"12\" y2=\"6\"/><line x1=\"2\" y1=\"9\" x2=\"12\" y2=\"9\"/><line x1=\"2\" y1=\"12\" x2=\"12\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatNone: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"3\" y1=\"19\" x2=\"17\" y2=\"19\"/></svg>`,\n alignCenter: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"7\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\"/><line x1=\"6\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n originalSize:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/></svg>`,\n deleteImg: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n caption: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"11\" rx=\"2\"/><line x1=\"6\" y1=\"18\" x2=\"18\" y2=\"18\"/><line x1=\"9\" y1=\"21\" x2=\"15\" y2=\"21\"/></svg>`,\n rotateLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"/><polyline points=\"3 3 3 8 8 8\"/></svg>`,\n rotateRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 12a9 9 0 1 1-9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\"/><polyline points=\"21 3 21 8 16 8\"/></svg>`,\n crop: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 2 6 18 22 18\"/><polyline points=\"2 6 18 6 18 22\"/></svg>`,\n};\n\nconst SHOW_DELAY = 100;\nconst HIDE_DELAY = 180;\n\nexport class ImageTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeImg = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const img = e.target.closest('img');\n // Skip when the image is inside a link — LinkTooltip takes priority there\n if (img && editable.contains(img) && !img.closest('a[href]')) {\n this._scheduleShow(img);\n }\n }, { passive: true }),\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }, { passive: true }),\n // Hide when image is deselected by clicking elsewhere\n on(document, 'click', (e) => {\n if (this._activeImg && !this._activeImg.contains(e.target) && !this._el.contains(e.target)) {\n this._hide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.image;\n const el = createElement('div', {\n class: 'an-link-tooltip an-image-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label showing \"Image\"\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._floatLeftBtn = this._makeBtn(ICONS.floatLeft, L.floatLeft, () => this._setFloat('left'));\n this._floatNoneBtn = this._makeBtn(ICONS.floatNone, L.noFloat, () => this._setFloat(''));\n this._alignCenterBtn = this._makeBtn(ICONS.alignCenter, L.alignCenter, () => this._setCenter());\n this._floatRightBtn = this._makeBtn(ICONS.floatRight, L.floatRight, () => this._setFloat('right'));\n\n el.appendChild(this._floatLeftBtn);\n el.appendChild(this._floatNoneBtn);\n el.appendChild(this._alignCenterBtn);\n el.appendChild(this._floatRightBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._originalBtn = this._makeBtn(ICONS.originalSize, L.originalSize, () => this._resetSize());\n\n el.appendChild(this._originalBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n el.appendChild(this._makeBtn(ICONS.rotateLeft, L.rotateLeft, () => this._rotate(-90)));\n el.appendChild(this._makeBtn(ICONS.rotateRight, L.rotateRight, () => this._rotate(90)));\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._cropBtn = this._makeBtn(ICONS.crop, L.cropImage, () => this._crop());\n el.appendChild(this._cropBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._captionBtn = this._makeBtn(ICONS.caption, L.addCaption, () => this._toggleCaption());\n el.appendChild(this._captionBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._deleteBtn = this._makeBtn(ICONS.deleteImg, L.deleteImage, () => this._delete(), true);\n\n el.appendChild(this._deleteBtn);\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger ? 'an-link-tooltip-btn an-link-tooltip-btn--danger' : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(img) {\n if (this._activeImg === img && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeImg = img;\n this._show(img);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n // Always reset the hide timer so rapid mouseout→mouseover sequences\n // don't leave a stale timer that hides the tooltip prematurely.\n clearTimeout(this._hideTimer);\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show(img) {\n this._el.style.display = 'flex';\n // Defer positioning: offsetWidth on a newly-visible element forces layout\n requestAnimationFrame(() => {\n if (this._activeImg) this._positionNear(this._activeImg);\n });\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activeImg = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(img) {\n const rect = img.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 220;\n const tipH = this._el.offsetHeight || 32;\n const margin = 6;\n\n let top = rect.bottom + margin;\n let left = rect.left + (rect.width - tipW) / 2;\n\n if (top + tipH > window.innerHeight - margin) top = rect.top - tipH - margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const img = this._activeImg;\n if (!img) return;\n const target = img.closest('figure.an-figure') || img;\n target.style.float = value;\n target.style.display = '';\n // Clear explicit width set for centering so the figure is free to float\n if (target !== img) target.style.width = '';\n target.style.marginLeft = value === 'right' ? '12px' : '';\n target.style.marginRight = value === 'left' ? '12px' : '';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n _setCenter() {\n const img = this._activeImg;\n if (!img) return;\n const target = img.closest('figure.an-figure') || img;\n target.style.float = '';\n target.style.display = 'block';\n // C1/C3: use fit-content so the block figure shrinks to the image width;\n // without an explicit width, margin:auto has no effect on a 100%-wide block.\n if (target !== img) target.style.width = 'fit-content';\n target.style.marginLeft = 'auto';\n target.style.marginRight = 'auto';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n _resetSize() {\n const img = this._activeImg;\n if (!img) return;\n img.style.width = '';\n img.style.height = '';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n /**\n * Rotate the active image by `delta` degrees (±90).\n * Reads the existing rotate() value from the transform style so\n * repeated clicks accumulate correctly.\n * @param {number} delta\n */\n _rotate(delta) {\n const img = this._activeImg;\n if (!img) return;\n // Parse current rotation angle from inline transform\n const current = img.style.transform || '';\n const match = current.match(/rotate\\((-?[\\d.]+)deg\\)/);\n const prev = match ? parseFloat(match[1]) : 0;\n const next = (prev + delta + 360) % 360; // normalise to [0, 360)\n // Preserve any other transform functions (e.g. scale), replace only rotate()\n const cleaned = current.replace(/rotate\\(-?[\\d.]+deg\\)/, '').trim();\n img.style.transform = cleaned\n ? `${cleaned} rotate(${next}deg)`\n : next === 0 ? '' : `rotate(${next}deg)`;\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeImg) this._positionNear(this._activeImg); });\n }\n\n _delete() {\n const img = this._activeImg;\n if (!img) return;\n this._hide();\n this.context.invoke('imageResizer.deselect');\n const figure = img.closest('figure.an-figure');\n if (figure && figure.parentNode) {\n figure.parentNode.removeChild(figure);\n } else if (img.parentNode) {\n img.parentNode.removeChild(img);\n }\n this.context.invoke('editor.afterCommand');\n }\n\n _crop() {\n const img = this._activeImg;\n if (!img) return;\n // Hide the tooltip while the crop overlay is active\n this._hide();\n // Delegate to imageCropOverlay module\n this.context.invoke('imageCropOverlay.open', img);\n }\n\n _toggleCaption() {\n const img = this._activeImg;\n if (!img) return;\n\n // If already inside a figure, move focus to the figcaption\n const existing = img.closest('figure.an-figure');\n if (existing) {\n const cap = existing.querySelector('figcaption.an-figcaption');\n if (cap) {\n this._hide();\n const range = document.createRange();\n range.selectNodeContents(cap);\n const sel = window.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(range); }\n }\n return;\n }\n\n // Wrap image in <figure><figcaption>\n const figure = document.createElement('figure');\n figure.className = 'an-figure';\n\n // Transfer existing alignment from <img> to <figure> (C4 fix)\n if (img.style.float) {\n figure.style.float = img.style.float;\n figure.style.marginLeft = img.style.marginLeft;\n figure.style.marginRight = img.style.marginRight;\n img.style.float = '';\n img.style.marginLeft = '';\n img.style.marginRight = '';\n } else if (img.style.display === 'block' && img.style.marginLeft === 'auto') {\n // C1/C3: use fit-content so the centered block figure tightly wraps the\n // image, making margin:auto actually centre it regardless of image width.\n figure.style.display = 'block';\n figure.style.width = 'fit-content';\n figure.style.marginLeft = 'auto';\n figure.style.marginRight = 'auto';\n img.style.display = '';\n img.style.marginLeft = '';\n img.style.marginRight = '';\n }\n const figcaption = document.createElement('figcaption');\n figcaption.className = 'an-figcaption';\n figcaption.textContent = 'Caption';\n\n img.parentNode.insertBefore(figure, img);\n figure.appendChild(img);\n figure.appendChild(figcaption);\n\n // Select caption text immediately\n const range = document.createRange();\n range.selectNodeContents(figcaption);\n const sel = window.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(range); }\n\n this.context.invoke('editor.afterCommand');\n // Re-sync the resize overlay: wrapping img in <figure> changes its layout position.\n this.context.invoke('imageResizer.updateOverlay');\n this._hide();\n }\n}\n","// VideoTooltip.js - Hover tooltip for video wrappers inside the editor\n// Displays a horizontal action bar below (or above) the selected video,\n// similar in appearance and interaction to LinkTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst ICONS = {\n floatLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"6\" x2=\"22\" y2=\"6\"/><line x1=\"12\" y1=\"9\" x2=\"22\" y2=\"9\"/><line x1=\"12\" y1=\"12\" x2=\"22\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"14\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"2\" y1=\"6\" x2=\"12\" y2=\"6\"/><line x1=\"2\" y1=\"9\" x2=\"12\" y2=\"9\"/><line x1=\"2\" y1=\"12\" x2=\"12\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatNone: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"3\" y1=\"19\" x2=\"17\" y2=\"19\"/></svg>`,\n alignCenter: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"7\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\"/><line x1=\"6\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n originalSize:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/></svg>`,\n deleteVideo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n preview: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"5 3 19 12 5 21 5 3\"/></svg>`,\n};\n\nconst SHOW_DELAY = 100;\nconst HIDE_DELAY = 180;\n\nexport class VideoTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeWrapper = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n this._previewMode = false;\n this._previewClickOff = null;\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n // The shield div sits on top of iframes — we detect hover via it or the wrapper\n const wrapper = e.target.closest('.an-video-wrapper');\n if (wrapper && editable.contains(wrapper)) {\n this._scheduleShow(wrapper);\n }\n }, { passive: true }),\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n if (\n this._activeWrapper &&\n !this._activeWrapper.contains(e.target) &&\n !this._el.contains(e.target)\n ) {\n this._hide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n if (this._previewMode) this._exitPreview();\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.video;\n const el = createElement('div', {\n class: 'an-link-tooltip an-video-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._floatLeftBtn = this._makeBtn(ICONS.floatLeft, L.floatLeft, () => this._setFloat('left'));\n this._floatNoneBtn = this._makeBtn(ICONS.floatNone, L.noFloat, () => this._setFloat(''));\n this._alignCenterBtn = this._makeBtn(ICONS.alignCenter, L.alignCenter, () => this._setCenter());\n this._floatRightBtn = this._makeBtn(ICONS.floatRight, L.floatRight, () => this._setFloat('right'));\n\n el.appendChild(this._floatLeftBtn);\n el.appendChild(this._floatNoneBtn);\n el.appendChild(this._alignCenterBtn);\n el.appendChild(this._floatRightBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._originalBtn = this._makeBtn(ICONS.originalSize, L.originalSize, () => this._resetSize());\n\n el.appendChild(this._originalBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._previewBtn = this._makeBtn(ICONS.preview, L.previewVideo, () => this._togglePreview());\n el.appendChild(this._previewBtn);\n\n el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));\n\n this._deleteBtn = this._makeBtn(ICONS.deleteVideo, L.deleteVideo, () => this._delete(), true);\n\n el.appendChild(this._deleteBtn);\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger ? 'an-link-tooltip-btn an-link-tooltip-btn--danger' : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(wrapper) {\n if (this._activeWrapper === wrapper && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeWrapper = wrapper;\n this._show(wrapper);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n // Keep tooltip alive while preview mode is active\n if (this._previewMode) return;\n clearTimeout(this._showTimer);\n this._showTimer = null;\n if (this._hideTimer) return;\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show(wrapper) {\n this._el.style.display = 'flex';\n // Defer: offsetWidth on a newly-visible element forces synchronous layout\n requestAnimationFrame(() => {\n if (this._activeWrapper) this._positionNear(this._activeWrapper);\n });\n }\n\n _hide() {\n if (this._previewMode) this._exitPreview();\n this._el.style.display = 'none';\n this._activeWrapper = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(wrapper) {\n const rect = wrapper.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 220;\n const tipH = this._el.offsetHeight || 32;\n const margin = 6;\n\n let top = rect.bottom + margin;\n let left = rect.left + (rect.width - tipW) / 2;\n\n if (top + tipH > window.innerHeight - margin) top = rect.top - tipH - margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n wrapper.style.float = value;\n wrapper.style.display = value ? 'inline-block' : '';\n wrapper.style.marginLeft = value === 'right' ? '12px' : '';\n wrapper.style.marginRight = value === 'left' ? '12px' : '';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('videoResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeWrapper) this._positionNear(this._activeWrapper); });\n }\n\n _setCenter() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n wrapper.style.float = '';\n wrapper.style.display = 'block';\n wrapper.style.marginLeft = 'auto';\n wrapper.style.marginRight = 'auto';\n this.context.invoke('editor.afterCommand');\n this.context.invoke('videoResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeWrapper) this._positionNear(this._activeWrapper); });\n }\n\n _resetSize() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n const embed = wrapper.querySelector('iframe, video');\n wrapper.style.width = '';\n wrapper.style.height = '';\n if (embed) {\n embed.removeAttribute('width');\n embed.removeAttribute('height');\n embed.style.width = '';\n embed.style.height = '';\n }\n this.context.invoke('editor.afterCommand');\n this.context.invoke('videoResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._activeWrapper) this._positionNear(this._activeWrapper); });\n }\n\n _delete() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n this._hide();\n this.context.invoke('videoResizer.deselect');\n if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Preview mode — temporarily disables the shield so the video is interactive\n // ---------------------------------------------------------------------------\n\n _togglePreview() {\n if (this._previewMode) {\n this._exitPreview();\n } else {\n this._enterPreview();\n }\n }\n\n _enterPreview() {\n const wrapper = this._activeWrapper;\n if (!wrapper) return;\n this._previewMode = true;\n\n // Hide the shield so the iframe / video receives pointer events directly\n const shield = wrapper.querySelector('.an-video-shield');\n if (shield) shield.style.display = 'none';\n\n // Hide the resize overlay — it would block interaction with the embed\n this.context.invoke('videoResizer.deselect');\n\n // Visual feedback: button turns primary-coloured\n this._previewBtn.classList.add('an-link-tooltip-btn--copied');\n this._previewBtn.title = this.context.locale.tooltips.video.exitPreview;\n\n // Exit preview on mousedown outside the wrapper.\n // Using 'mousedown' (not 'click') so clicks inside an iframe\n // — which never bubble to the outer document — don't accidentally\n // leave preview mode stuck. For <video> elements, mousedown on the\n // video is inside the wrapper so contains() returns true → no exit.\n this._previewClickOff = (e) => {\n if (!wrapper.contains(e.target) && !this._el.contains(e.target)) {\n this._exitPreview();\n }\n };\n document.addEventListener('mousedown', this._previewClickOff, true);\n }\n\n _exitPreview() {\n this._previewMode = false;\n\n const wrapper = this._activeWrapper;\n if (wrapper) {\n // Restore the shield\n const shield = wrapper.querySelector('.an-video-shield');\n if (shield) shield.style.display = '';\n }\n\n // Reset button appearance\n this._previewBtn.classList.remove('an-link-tooltip-btn--copied');\n this._previewBtn.title = this.context.locale.tooltips.video.previewVideo;\n\n if (this._previewClickOff) {\n document.removeEventListener('mousedown', this._previewClickOff, true);\n this._previewClickOff = null;\n }\n }\n}\n","// TableTooltip.js - Hover tooltip for tables inside the editor\n// Shows a horizontal action bar above (or below) the hovered table,\n// similar in appearance and interaction to ImageTooltip / VideoTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 200;\n\n// ---------------------------------------------------------------------------\n// Table helpers — visual column index (accounts for colspan)\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the visual (logical) column index of a cell, taking colspan into\n * account for all preceding cells in the same row.\n * @param {HTMLTableCellElement} cell\n * @returns {number} 0-based visual column index, or -1 on failure\n */\nfunction getVisualColIndex(cell) {\n const row = cell.closest('tr');\n if (!row) return -1;\n let visualIdx = 0;\n for (const c of row.cells) {\n if (c === cell) return visualIdx;\n visualIdx += c.colSpan || 1;\n }\n return -1;\n}\n\n/**\n * Finds the first cell in a row whose visual start column equals visualIdx.\n * Returns null if no exact match (e.g. the column is spanned by a merged cell).\n * @param {HTMLTableRowElement} row\n * @param {number} visualIdx\n * @returns {HTMLTableCellElement|null}\n */\nfunction getCellAtVisualCol(row, visualIdx) {\n let vIdx = 0;\n for (const c of row.cells) {\n if (vIdx === visualIdx) return c;\n if (vIdx > visualIdx) break;\n vIdx += c.colSpan || 1;\n }\n return null;\n}\n\n/**\n * Finds the first cell whose visual range ends after visualIdx\n * (used for inserting a new column to the right of visualIdx).\n * @param {HTMLTableRowElement} row\n * @param {number} visualIdx\n * @returns {HTMLTableCellElement|null} reference cell for insertBefore, or null = append\n */\nfunction getCellAfterVisualCol(row, visualIdx) {\n let vIdx = 0;\n for (const c of row.cells) {\n vIdx += c.colSpan || 1;\n if (vIdx > visualIdx) {\n // next cell after the one that starts at / spans visualIdx\n const next = c.nextElementSibling;\n return (next && next.tagName === 'TD' || next && next.tagName === 'TH') ? next : null;\n }\n }\n return null;\n}\n\n/**\n * Build a 2D grid map of the table, accounting for both rowspan and colspan.\n *\n * gridMap[r][c] = the DOM cell occupying visual grid position (r, c).\n * cellPos = WeakMap: cell → { r, c, rs, cs } (top-left grid origin + span).\n *\n * Uses HTMLTableElement.rows which is scoped to the table itself and never\n * includes rows from nested tables.\n *\n * @param {HTMLTableElement} table\n * @returns {{ gridMap: Object, cellPos: WeakMap }}\n */\nfunction buildGridMap(table) {\n const rows = Array.from(table.rows);\n const gridMap = {};\n const cellPos = new WeakMap();\n rows.forEach((row, r) => {\n if (!gridMap[r]) gridMap[r] = {};\n let c = 0;\n for (const cell of row.cells) {\n // Skip positions already occupied by a rowspan from a previous row\n while (gridMap[r][c]) c++;\n const rs = cell.rowSpan || 1;\n const cs = cell.colSpan || 1;\n cellPos.set(cell, { r, c, rs, cs });\n for (let dr = 0; dr < rs; dr++) {\n if (!gridMap[r + dr]) gridMap[r + dr] = {};\n for (let dc = 0; dc < cs; dc++) {\n gridMap[r + dr][c + dc] = cell;\n }\n }\n c += cs;\n }\n });\n return { gridMap, cellPos };\n}\n\nconst ICONS = {\n rowAbove: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/><path d=\"M12 3v7\"/><path d=\"M9 7l3-4 3 4\"/></svg>`,\n rowBelow: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/><path d=\"M12 12v7\"/><path d=\"M9 17l3 4 3-4\"/></svg>`,\n deleteRow: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"15\" y1=\"15\" x2=\"21\" y2=\"21\"/><line x1=\"21\" y1=\"15\" x2=\"15\" y2=\"21\"/></svg>`,\n colLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><path d=\"M3 12h7\"/><path d=\"M7 8l-4 4 4 4\"/></svg>`,\n colRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><path d=\"M12 12h9\"/><path d=\"M17 8l4 4-4 4\"/></svg>`,\n deleteCol: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><line x1=\"15\" y1=\"6\" x2=\"21\" y2=\"12\"/><line x1=\"21\" y1=\"6\" x2=\"15\" y2=\"12\"/></svg>`,\n mergeCells: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"7\" width=\"8\" height=\"10\" rx=\"1\"/><rect x=\"14\" y=\"7\" width=\"8\" height=\"10\" rx=\"1\"/><path d=\"M10 12h4\"/><path d=\"M12 10l2 2-2 2\"/></svg>`,\n unmergeCells: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"1\"/><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" stroke-dasharray=\"2.5 2\"/><line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\" stroke-dasharray=\"2.5 2\"/><path d=\"M9 9 L6 12 L9 15\"/><path d=\"M15 9 L18 12 L15 15\"/></svg>`,\n colWidth: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"7\" y1=\"4\" x2=\"7\" y2=\"20\"/><line x1=\"17\" y1=\"4\" x2=\"17\" y2=\"20\"/><line x1=\"7\" y1=\"12\" x2=\"17\" y2=\"12\"/><path d=\"M10 9l-3 3 3 3\"/><path d=\"M14 9l3 3-3 3\"/></svg>`,\n rowHeight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"4\" y1=\"7\" x2=\"20\" y2=\"7\"/><line x1=\"4\" y1=\"17\" x2=\"20\" y2=\"17\"/><line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"17\"/><path d=\"M9 10l3-3 3 3\"/><path d=\"M9 14l3 3 3-3\"/></svg>`,\n tableBorder: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" stroke-width=\"1\"/><line x1=\"3\" y1=\"13\" x2=\"21\" y2=\"13\" stroke-width=\"2\"/><line x1=\"3\" y1=\"20\" x2=\"21\" y2=\"20\" stroke-width=\"3\"/></svg>`,\n deleteTable: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/><line x1=\"16\" y1=\"16\" x2=\"22\" y2=\"22\" stroke=\"#ef4444\"/><line x1=\"22\" y1=\"16\" x2=\"16\" y2=\"22\" stroke=\"#ef4444\"/></svg>`,\n selectCells: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z\" fill=\"currentColor\" opacity=\"0.15\"/><path d=\"M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z\"/></svg>`,\n};\n\nexport class TableTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activeTable = null;\n this._activeCell = null; // last hovered td/th\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n this._sizePopover = null;\n this._sizeApply = null;\n this._sizeTitleEl = null;\n this._sizeInputEl = null;\n // Cell selection\n this._selectMode = false;\n this._selectedCells = [];\n this._selectStart = null;\n this._selectDragging = false;\n this._selectBtn = null;\n this._editable = null;\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n\n this._sizePopover = this._buildSizePopover();\n document.body.appendChild(this._sizePopover);\n\n const editable = this.context.layoutInfo.editable;\n this._editable = editable;\n\n // ── Cell selection drag ──────────────────────────────────────────────────\n const onSelMousedown = (e) => {\n if (!this._selectMode) return;\n const cell = e.target.closest('td, th');\n if (!cell || !editable.contains(cell)) return;\n // Don't interfere with col/row resize (inline cursor is set by resize logic)\n if (cell.style.cursor === 'col-resize' || cell.style.cursor === 'row-resize') return;\n e.preventDefault(); // suppress text-cursor placement while selecting cells\n this._activeTable = cell.closest('table');\n this._selectStart = cell;\n this._selectDragging = true;\n this._setSelection([cell]);\n };\n const onSelMousemove = (e) => {\n if (!this._selectMode || !this._selectDragging || !this._selectStart) return;\n const cell = e.target.closest('td, th');\n if (!cell || !editable.contains(cell)) return;\n if (cell.closest('table') !== this._activeTable) return;\n this._setSelection(this._getRectCells(this._selectStart, cell));\n };\n const onSelMouseup = () => { this._selectDragging = false; };\n\n this._disposers.push(\n on(editable, 'mousedown', onSelMousedown),\n on(editable, 'mousemove', onSelMousemove),\n on(document, 'mouseup', onSelMouseup),\n );\n // ────────────────────────────────────────────────────────────────────────\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const table = e.target.closest('table');\n if (table && editable.contains(table)) {\n const cell = e.target.closest('td, th');\n if (cell) this._activeCell = cell;\n this._scheduleShow(table);\n }\n }, { passive: true }),\n on(editable, 'mouseout', (e) => {\n if (this._selectMode) return; // keep tooltip alive during cell selection\n const to = e.relatedTarget;\n if (!to || (\n !editable.contains(to) &&\n !this._el.contains(to) &&\n !(this._sizePopover && this._sizePopover.contains(to))\n )) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n if (this._selectMode && this._activeTable && this._activeTable.contains(e.target)) return;\n if (this._activeTable &&\n !this._activeTable.contains(e.target) &&\n !this._el.contains(e.target) &&\n !(this._sizePopover && this._sizePopover.contains(e.target))) {\n this._hide();\n }\n }),\n );\n\n this._initResize();\n return this;\n }\n\n // ---------------------------------------------------------------------------\n // Column & row drag-resize\n // ---------------------------------------------------------------------------\n\n _initResize() {\n const editable = this.context.layoutInfo.editable;\n const HIT = 6; // px proximity threshold\n\n // Shared hover state\n let _nearCell = null;\n let _nearEdge = null; // 'col' | 'row' | null\n\n // Active drag state\n let _resizing = false;\n let _edge = null; // 'col' | 'row'\n let _startX = 0;\n let _startY = 0;\n let _startW = 0;\n let _startH = 0;\n let _colIdx = -1;\n let _colCells = null; // cells cached at drag-start — avoids querySelectorAll every frame\n let _row = null;\n let _table = null;\n let _rafDocMove = null; // pending rAF handle for resize drag\n let _rafEditorMove = null; // pending rAF handle for cursor detection\n\n const clearHover = () => {\n if (_nearCell) { _nearCell.style.cursor = ''; _nearCell = null; }\n _nearEdge = null;\n };\n\n const onEditorMove = (e) => {\n if (_resizing) return;\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) {\n clearHover();\n return;\n }\n // Throttle to one check per animation frame — getBoundingClientRect forces reflow\n if (_rafEditorMove !== null) return;\n const target = e.target;\n const clientX = e.clientX;\n const clientY = e.clientY;\n _rafEditorMove = requestAnimationFrame(() => {\n _rafEditorMove = null;\n const cell = target.closest('td, th');\n if (!cell || !editable.contains(cell)) { clearHover(); return; }\n if (_nearCell && _nearCell !== cell) _nearCell.style.cursor = '';\n const rect = cell.getBoundingClientRect();\n const onRight = Math.abs(clientX - rect.right) < HIT;\n const onBottom = Math.abs(clientY - rect.bottom) < HIT;\n if (onRight) {\n cell.style.cursor = 'col-resize';\n _nearCell = cell; _nearEdge = 'col';\n } else if (onBottom) {\n cell.style.cursor = 'row-resize';\n _nearCell = cell; _nearEdge = 'row';\n } else {\n clearHover();\n }\n });\n };\n\n const onEditorDown = (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n if (!_nearCell || !_nearEdge) return;\n _resizing = true;\n _edge = _nearEdge;\n _startX = e.clientX;\n _startY = e.clientY;\n _table = _nearCell.closest('table');\n if (_edge === 'col') {\n _startW = _nearCell.offsetWidth;\n _colIdx = getVisualColIndex(_nearCell);\n // Cache column cells once so onDocMove never runs querySelectorAll per frame.\n // F-1: skip merged cells (colSpan > 1) — setting width on a merged cell\n // distributes it equally across all spanned columns instead of resizing\n // only the target column. Rows that have an individual cell at this\n // visual column index are resized independently as expected.\n _colCells = _colIdx >= 0\n ? Array.from(_table.querySelectorAll('tr'))\n .map(r => getCellAtVisualCol(r, _colIdx))\n .filter(Boolean)\n .filter(c => (c.colSpan || 1) === 1)\n : [];\n document.body.style.cursor = 'col-resize';\n } else {\n _row = _nearCell.closest('tr');\n _startH = _row ? _row.offsetHeight : 40;\n document.body.style.cursor = 'row-resize';\n }\n document.body.style.userSelect = 'none';\n e.preventDefault();\n e.stopPropagation();\n };\n\n const onDocMove = (e) => {\n if (!_resizing) return;\n // Skip if a frame is already scheduled — avoids per-pixel style thrashing\n if (_rafDocMove !== null) return;\n const clientX = e.clientX;\n const clientY = e.clientY;\n _rafDocMove = requestAnimationFrame(() => {\n _rafDocMove = null;\n if (_edge === 'col') {\n const newW = Math.max(30, _startW + (clientX - _startX));\n for (const c of _colCells) {\n c.style.width = `${newW}px`;\n c.style.minWidth = `${newW}px`;\n }\n } else {\n const newH = Math.max(20, _startH + (clientY - _startY));\n if (_row) {\n for (const c of _row.cells) {\n c.style.height = `${newH}px`;\n c.style.minHeight = `${newH}px`;\n }\n }\n }\n });\n };\n\n const onDocUp = () => {\n if (!_resizing) return;\n // Cancel any in-flight rAF so stale writes don't land after mouseup\n if (_rafDocMove !== null) { cancelAnimationFrame(_rafDocMove); _rafDocMove = null; }\n _resizing = false;\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n _edge = null;\n _table = null;\n _row = null;\n _colIdx = -1;\n _colCells = null;\n this.context.invoke('editor.afterCommand');\n };\n\n this._disposers.push(\n on(editable, 'mousemove', onEditorMove),\n on(editable, 'mousedown', onEditorDown),\n on(document, 'mousemove', onDocMove),\n on(document, 'mouseup', onDocUp),\n );\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n if (this._sizePopover && this._sizePopover.parentNode) {\n this._sizePopover.parentNode.removeChild(this._sizePopover);\n }\n this._sizePopover = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build tooltip bar\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.table;\n const el = createElement('div', {\n class: 'an-link-tooltip an-table-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(this._sep());\n\n // Select-cells toggle\n this._selectBtn = this._makeBtn(ICONS.selectCells, L.selectCells, () => this._toggleSelectMode());\n el.appendChild(this._selectBtn);\n\n el.appendChild(this._sep());\n\n // Row operations\n el.appendChild(this._makeBtn(ICONS.rowAbove, L.addRowAbove, () => this._addRow('above')));\n el.appendChild(this._makeBtn(ICONS.rowBelow, L.addRowBelow, () => this._addRow('below')));\n el.appendChild(this._makeBtn(ICONS.deleteRow, L.deleteRow, () => this._deleteRow()));\n\n el.appendChild(this._sep());\n\n // Column operations\n el.appendChild(this._makeBtn(ICONS.colLeft, L.addColumnLeft, () => this._addColumn('left')));\n el.appendChild(this._makeBtn(ICONS.colRight, L.addColumnRight, () => this._addColumn('right')));\n el.appendChild(this._makeBtn(ICONS.deleteCol, L.deleteColumn, () => this._deleteColumn()));\n\n el.appendChild(this._sep());\n\n // Merge cells\n el.appendChild(this._makeBtn(ICONS.mergeCells, L.mergeCells, () => this._mergeCells()));\n el.appendChild(this._makeBtn(ICONS.unmergeCells, L.unmergeCells, () => this._unmergeCells()));\n\n el.appendChild(this._sep());\n\n // Resize\n el.appendChild(this._makeBtn(ICONS.colWidth, L.columnWidth, () => this._openSizePopover('col')));\n el.appendChild(this._makeBtn(ICONS.rowHeight, L.rowHeight, () => this._openSizePopover('row')));\n el.appendChild(this._makeBtn(ICONS.tableBorder,L.tableBorderWidth, () => this._openSizePopover('border')));\n\n el.appendChild(this._sep());\n\n // Delete table (danger)\n el.appendChild(this._makeBtn(ICONS.deleteTable, L.deleteTable, () => this._deleteTable(), true));\n\n // Keep tooltip alive while hovering.\n // Don't schedule hide on mouseleave when the size popover is open —\n // the user is moving the mouse toward it.\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => {\n if (this._selectMode) return; // keep tooltip alive during cell selection\n if (this._sizePopover && this._sizePopover.style.display !== 'none') return;\n this._scheduleHide();\n }),\n );\n\n return el;\n }\n\n _sep() {\n return createElement('div', { class: 'an-link-tooltip-sep' });\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger\n ? 'an-link-tooltip-btn an-link-tooltip-btn--danger'\n : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(table) {\n if (this._activeTable === table && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activeTable = table;\n this._show();\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n if (this._hideTimer) return;\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show() {\n if (!this._activeTable) return;\n this._el.style.display = 'flex';\n // Defer: offsetWidth on a newly-visible element forces layout synchronously\n requestAnimationFrame(() => {\n if (this._activeTable) this._positionNear(this._activeTable);\n });\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activeTable = null;\n this._activeCell = null;\n // Reset select mode\n if (this._selectMode) {\n this._selectMode = false;\n if (this._selectBtn) this._selectBtn.classList.remove('an-link-tooltip-btn--active');\n if (this._editable) this._editable.classList.remove('an-table-select-mode');\n }\n this._clearSelection();\n this._clearTimers();\n this._hideSizePopover();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(table) {\n if (!table) return;\n const rect = table.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 400;\n const tipH = this._el.offsetHeight || 30;\n const margin = 6;\n\n // Center horizontally over the table; prefer above it\n let left = rect.left + (rect.width - tipW) / 2;\n let top = rect.top - tipH - margin;\n\n if (top < margin) top = rect.bottom + margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n this._el.style.left = `${left}px`;\n this._el.style.top = `${top}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Helper: get active cell (fallback to first td/th in table)\n // ---------------------------------------------------------------------------\n\n _getCell() {\n // Prefer the cell under the current text cursor (most intuitive for operations)\n const sel = window.getSelection();\n if (sel && sel.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const cellFromSel = container && container.closest && container.closest('td, th');\n if (cellFromSel && this._activeTable && this._activeTable.contains(cellFromSel)) {\n return cellFromSel;\n }\n }\n return this._activeCell\n || (this._activeTable && this._activeTable.querySelector('td, th'));\n }\n\n // ---------------------------------------------------------------------------\n // Cell selection helpers\n // ---------------------------------------------------------------------------\n\n _toggleSelectMode() {\n this._selectMode = !this._selectMode;\n if (this._selectBtn) {\n this._selectBtn.classList.toggle('an-link-tooltip-btn--active', this._selectMode);\n }\n if (this._editable) {\n this._editable.classList.toggle('an-table-select-mode', this._selectMode);\n }\n if (!this._selectMode) {\n this._clearSelection();\n }\n }\n\n _clearSelection() {\n this._selectedCells.forEach((c) => c.classList.remove('an-cell-selected'));\n this._selectedCells = [];\n this._selectStart = null;\n }\n\n _setSelection(cells) {\n // Remove highlight from cells no longer in selection\n this._selectedCells.forEach((c) => {\n if (!cells.includes(c)) c.classList.remove('an-cell-selected');\n });\n this._selectedCells = cells;\n cells.forEach((c) => c.classList.add('an-cell-selected'));\n }\n\n /**\n * Returns all cells in the rectangular area between startCell and endCell,\n * correctly handling rowspan/colspan by using the grid map.\n * The rect is expanded iteratively until it is stable — this ensures any\n * merged cell that starts outside the initial rect but spans into it is\n * fully included.\n */\n _getRectCells(startCell, endCell) {\n if (!startCell) return [];\n if (!endCell || startCell === endCell) return [startCell];\n const table = startCell.closest('table');\n if (!table || !table.contains(endCell)) return [startCell];\n\n const { gridMap, cellPos } = buildGridMap(table);\n const sp = cellPos.get(startCell);\n const ep = cellPos.get(endCell);\n if (!sp || !ep) return [startCell];\n\n let minR = Math.min(sp.r, ep.r);\n let maxR = Math.max(sp.r + sp.rs - 1, ep.r + ep.rs - 1);\n let minC = Math.min(sp.c, ep.c);\n let maxC = Math.max(sp.c + sp.cs - 1, ep.c + ep.cs - 1);\n\n // Iteratively expand until stable — handles spans that exceed the current rect\n let changed = true;\n while (changed) {\n changed = false;\n for (let r = minR; r <= maxR; r++) {\n const rowMap = gridMap[r];\n if (!rowMap) continue;\n for (let c = minC; c <= maxC; c++) {\n const cell = rowMap[c];\n if (!cell) continue;\n const pos = cellPos.get(cell);\n if (!pos) continue;\n if (pos.r < minR) { minR = pos.r; changed = true; }\n if (pos.r + pos.rs - 1 > maxR) { maxR = pos.r + pos.rs - 1; changed = true; }\n if (pos.c < minC) { minC = pos.c; changed = true; }\n if (pos.c + pos.cs - 1 > maxC) { maxC = pos.c + pos.cs - 1; changed = true; }\n }\n }\n }\n\n // Collect unique cells in document order\n const seen = new Set();\n const result = [];\n for (let r = minR; r <= maxR; r++) {\n const rowMap = gridMap[r];\n if (!rowMap) continue;\n for (let c = minC; c <= maxC; c++) {\n const cell = rowMap[c];\n if (cell && !seen.has(cell)) {\n seen.add(cell);\n result.push(cell);\n }\n }\n }\n return result.length > 0 ? result : [startCell];\n }\n\n /**\n * Returns the active cell set: user-selected cells when available,\n * otherwise the single active/cursor cell.\n * @returns {HTMLTableCellElement[]}\n */\n _getSelectedCells() {\n return this._selectedCells.length > 0\n ? this._selectedCells\n : [this._getCell()].filter(Boolean);\n }\n\n // ---------------------------------------------------------------------------\n // Table operations\n // ---------------------------------------------------------------------------\n\n _addRow(position) {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const allRows = Array.from(table.querySelectorAll('tr'));\n const selectedRows = [...new Set(cells.map((c) => c.closest('tr')).filter(Boolean))];\n // Reference row: topmost for 'above', bottommost for 'below'\n const refRow = selectedRows.reduce((best, r) => {\n const bi = allRows.indexOf(best);\n const ri = allRows.indexOf(r);\n return position === 'above' ? (ri < bi ? r : best) : (ri > bi ? r : best);\n });\n const colCount = Array.from(refRow.cells).reduce((sum, c) => sum + (c.colSpan || 1), 0);\n const newRow = document.createElement('tr');\n const refCells = Array.from(refRow.cells);\n for (let i = 0; i < colCount; i++) {\n const td = createElement('td', {}, ['\\u00a0']);\n const ref = refCells[i];\n if (ref && ref.style.width) td.style.width = ref.style.width;\n if (ref && ref.style.minWidth) td.style.minWidth = ref.style.minWidth;\n newRow.appendChild(td);\n }\n if (position === 'above') refRow.parentElement?.insertBefore(newRow, refRow);\n else refRow.insertAdjacentElement('afterend', newRow);\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _addColumn(position) {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const colIndices = cells.map((c) => getVisualColIndex(c));\n const targetColIdx = position === 'left' ? Math.min(...colIndices) : Math.max(...colIndices);\n const rows = Array.from(table.querySelectorAll('tr'));\n const refs = rows.map((r) => position === 'left'\n ? getCellAtVisualCol(r, targetColIdx)\n : getCellAfterVisualCol(r, targetColIdx));\n const isHeaders = rows.map((r) => r.closest('thead') !== null);\n rows.forEach((r, i) => {\n r.insertBefore(createElement(isHeaders[i] ? 'th' : 'td', {}, ['\\u00a0']), refs[i]);\n });\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _deleteRow() {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const tbody = table.querySelector('tbody');\n const totalBodyRows = tbody\n ? tbody.querySelectorAll('tr').length\n : table.querySelectorAll('tr').length;\n const selectedRows = [...new Set(cells.map((c) => c.closest('tr')).filter(Boolean))];\n const bodyRowsToDelete = selectedRows.filter((r) => r.closest('tbody'));\n // Guard: keep at least one body row\n if (bodyRowsToDelete.length >= totalBodyRows) return;\n this._activeCell = null;\n this._clearSelection();\n selectedRows.forEach((r) => r.parentElement?.removeChild(r));\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _deleteColumn() {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const tableRows = Array.from(table.querySelectorAll('tr'));\n if (tableRows[0] && tableRows[0].cells.length <= 1) return; // guard: keep ≥1 col\n const colIndices = [...new Set(cells.map((c) => getVisualColIndex(c)))];\n if (colIndices.length >= (tableRows[0]?.cells.length ?? 1)) return;\n // Collect all cell references upfront before any removal (avoids stale visual indices)\n const cellsToDelete = [];\n colIndices.forEach((colIdx) => {\n tableRows.forEach((r) => {\n const c = getCellAtVisualCol(r, colIdx);\n if (c) cellsToDelete.push(c);\n });\n });\n this._activeCell = null;\n this._clearSelection();\n cellsToDelete.forEach((c) => c.parentElement?.removeChild(c));\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n _mergeCells() {\n const cell = this._getCell();\n if (!cell) return;\n const table = cell.closest('table');\n if (!table) return;\n\n // Prefer user panel-selected cells; fall back to text-selection range\n let selected = this._getSelectedCells().filter((c) => table.contains(c));\n if (selected.length < 2) {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n const allCells = Array.from(table.querySelectorAll('td, th'));\n selected = allCells.filter((c) => {\n try { return range.intersectsNode(c); } catch { return false; }\n });\n if (selected.length < 2) return;\n }\n\n const { gridMap, cellPos } = buildGridMap(table);\n\n // Bounding rect that encompasses every selected cell's full span\n let minR = Infinity, maxR = -Infinity, minC = Infinity, maxC = -Infinity;\n selected.forEach((c) => {\n const pos = cellPos.get(c);\n if (!pos) return;\n if (pos.r < minR) minR = pos.r;\n if (pos.r + pos.rs - 1 > maxR) maxR = pos.r + pos.rs - 1;\n if (pos.c < minC) minC = pos.c;\n if (pos.c + pos.cs - 1 > maxC) maxC = pos.c + pos.cs - 1;\n });\n if (minR === Infinity) return;\n\n // Collect every unique cell in the bounding rect\n const seen = new Set();\n const rectCells = [];\n for (let r = minR; r <= maxR; r++) {\n const rowMap = gridMap[r];\n if (!rowMap) continue;\n for (let c = minC; c <= maxC; c++) {\n const tc = rowMap[c];\n if (tc && !seen.has(tc)) { seen.add(tc); rectCells.push(tc); }\n }\n }\n if (rectCells.length < 2) return;\n\n const first = rectCells[0];\n first.colSpan = maxC - minC + 1;\n first.rowSpan = maxR - minR + 1;\n first.style.verticalAlign = 'middle';\n first.innerHTML = rectCells.map((c) => c.innerHTML).join('');\n rectCells.slice(1).forEach((c) => c.parentElement?.removeChild(c));\n\n this._clearSelection();\n this.context.invoke('editor.afterCommand');\n }\n\n _deleteTable() {\n const table = this._activeTable;\n if (!table) return;\n this._hide();\n if (table.parentNode) table.parentNode.removeChild(table);\n this.context.invoke('editor.afterCommand');\n }\n\n _unmergeCells() {\n const cells = this._getSelectedCells();\n if (!cells.length) return;\n const table = cells[0].closest('table');\n if (!table) return;\n const mergedCells = cells.filter(\n (c) => table.contains(c) && ((c.colSpan || 1) > 1 || (c.rowSpan || 1) > 1)\n );\n if (!mergedCells.length) return;\n mergedCells.forEach((cell) => {\n if (table.contains(cell)) this._unmergeOne(cell, table);\n });\n this._clearSelection();\n requestAnimationFrame(() => this._positionNear(this._activeTable));\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Split a single merged cell (colspan/rowspan > 1) back into individual cells.\n * New cells are empty ( ); the original cell retains its content.\n * @param {HTMLTableCellElement} cell\n * @param {HTMLTableElement} table\n */\n _unmergeOne(cell, table) {\n const cs = cell.colSpan || 1;\n const rs = cell.rowSpan || 1;\n if (cs === 1 && rs === 1) return;\n\n // Build grid map from current DOM state (before any mutation)\n const { cellPos } = buildGridMap(table);\n const pos = cellPos.get(cell);\n if (!pos) return;\n\n const { r, c } = pos;\n const tableRows = Array.from(table.rows);\n const tag = cell.tagName.toLowerCase(); // preserve td / th\n\n // Reset the original cell\n cell.rowSpan = 1;\n cell.colSpan = 1;\n cell.style.verticalAlign = '';\n\n // Same row: insert (cs - 1) sibling cells after the original cell\n if (cs > 1) {\n const insertRef = cell.nextElementSibling;\n for (let dc = 1; dc < cs; dc++) {\n tableRows[r].insertBefore(createElement(tag, {}, ['\\u00a0']), insertRef);\n }\n }\n\n // Rows below: insert cs cells at the correct visual column position (for rowspan)\n for (let dr = 1; dr < rs; dr++) {\n const targetRow = tableRows[r + dr];\n if (!targetRow) continue;\n // Find the first cell in this row whose visual-col origin is beyond c\n // (using cellPos built before mutations — valid for these untouched rows)\n let ref = null;\n for (const tc of targetRow.cells) {\n const tp = cellPos.get(tc);\n if (tp && tp.c > c) { ref = tc; break; }\n }\n for (let dc = 0; dc < cs; dc++) {\n targetRow.insertBefore(createElement(tag, {}, ['\\u00a0']), ref);\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Size popover (column width / row height)\n // ---------------------------------------------------------------------------\n\n _buildSizePopover() {\n const popover = createElement('div', { class: 'an-size-popover' });\n popover.style.display = 'none';\n\n const titleEl = createElement('div', { class: 'an-size-popover-title' });\n const body = createElement('div', { class: 'an-size-popover-body' });\n const inputEl = createElement('input', {\n type: 'number', class: 'an-size-input', min: '1', max: '2000', step: '1',\n });\n const unitEl = createElement('span', { class: 'an-size-unit' }, ['px']);\n body.appendChild(inputEl);\n body.appendChild(unitEl);\n\n const actionsEl = createElement('div', { class: 'an-size-popover-actions' });\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = this.context.locale.tooltips.table.cancelBtn;\n const applyBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n applyBtn.textContent = this.context.locale.tooltips.table.applyBtn;\n actionsEl.appendChild(cancelBtn);\n actionsEl.appendChild(applyBtn);\n\n popover.appendChild(titleEl);\n popover.appendChild(body);\n popover.appendChild(actionsEl);\n\n this._sizeTitleEl = titleEl;\n this._sizeInputEl = inputEl;\n this._sizeApply = null;\n\n const d1 = on(applyBtn, 'click', () => {\n const val = parseInt(this._sizeInputEl.value, 10);\n if (val > 0 && typeof this._sizeApply === 'function') this._sizeApply(val);\n this._hideSizePopover();\n });\n const d2 = on(cancelBtn, 'click', () => this._hideSizePopover());\n const d3 = on(inputEl, 'keydown', (e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (e.key === 'Escape') this._hideSizePopover();\n });\n const d4 = on(document, 'click', (e) => {\n if (this._sizePopover &&\n this._sizePopover.style.display !== 'none' &&\n !this._sizePopover.contains(e.target) &&\n !this._el.contains(e.target)) {\n this._hideSizePopover();\n }\n });\n // Keep the tooltip/popover alive while the mouse is over the popover.\n const d5 = on(popover, 'mouseenter', () => this._clearTimers());\n const d6 = on(popover, 'mouseleave', () => this._scheduleHide());\n this._disposers.push(d1, d2, d3, d4, d5, d6);\n return popover;\n }\n\n _openSizePopover(type) {\n const cell = this._getCell();\n if (!cell || !this._sizePopover) return;\n\n if (type === 'border') {\n const table = cell.closest('table');\n if (!table) return;\n const firstCell = table.querySelector('td, th');\n const currentPx = firstCell\n ? (parseInt(firstCell.style.borderWidth, 10) ||\n parseInt(window.getComputedStyle(firstCell).borderWidth, 10) || 1)\n : 1;\n this._sizeTitleEl.textContent = this.context.locale.tooltips.table.tableBorderWidthPx;\n this._sizeInputEl.min = '0';\n this._sizeInputEl.max = '10';\n this._sizeInputEl.value = currentPx;\n this._sizeApply = (val) => {\n const cells = Array.from(table.querySelectorAll('td, th'));\n if (val === 0) {\n cells.forEach((c) => { c.style.borderWidth = '0'; c.style.borderStyle = 'none'; });\n } else {\n cells.forEach((c) => { c.style.borderWidth = `${val}px`; c.style.borderStyle = 'solid'; });\n }\n this.context.invoke('editor.afterCommand');\n };\n } else {\n const isCol = type === 'col';\n const activeCells = this._getSelectedCells().filter((c) => {\n const t = c.closest('table');\n return t && t === cell.closest('table');\n });\n this._sizeTitleEl.textContent = isCol\n ? this.context.locale.tooltips.table.columnWidthPx\n : this.context.locale.tooltips.table.rowHeightPx;\n this._sizeInputEl.min = '1';\n this._sizeInputEl.max = '2000';\n this._sizeInputEl.value = isCol\n ? (cell.offsetWidth || 120)\n : (cell.closest('tr') ? (cell.closest('tr').offsetHeight || 40) : 40);\n this._sizeApply = (val) => {\n const table = cell.closest('table');\n if (!table) return;\n if (isCol) {\n // Apply to all selected columns (or just the current column)\n const colIndices = [...new Set(activeCells.map((c) => getVisualColIndex(c)))];\n const tableRows = Array.from(table.querySelectorAll('tr'));\n colIndices.forEach((colIdx) => {\n tableRows.forEach((r) => {\n const c = getCellAtVisualCol(r, colIdx);\n // F-1: skip merged cells — same reason as drag-resize _colCells.\n if (c && (c.colSpan || 1) === 1) { c.style.width = `${val}px`; c.style.minWidth = `${val}px`; }\n });\n });\n } else {\n // Apply to all selected rows (or just the current row)\n const selectedRows = [...new Set(activeCells.map((c) => c.closest('tr')).filter(Boolean))];\n selectedRows.forEach((row) => {\n for (const c of row.cells) { c.style.height = `${val}px`; c.style.minHeight = `${val}px`; }\n });\n }\n this.context.invoke('editor.afterCommand');\n };\n }\n\n this._sizePopover.style.display = 'block';\n requestAnimationFrame(() => {\n if (!this._sizePopover || !this._el) return;\n const tipRect = this._el.getBoundingClientRect();\n const pw = this._sizePopover.offsetWidth || 220;\n const ph = this._sizePopover.offsetHeight || 110;\n let left = tipRect.left;\n let top = tipRect.bottom + 6;\n if (left + pw > window.innerWidth - 8) left = window.innerWidth - pw - 8;\n if (top + ph > window.innerHeight - 8) top = tipRect.top - ph - 6;\n this._sizePopover.style.left = `${left}px`;\n this._sizePopover.style.top = `${top}px`;\n if (this._sizeInputEl) { this._sizeInputEl.focus(); this._sizeInputEl.select(); }\n });\n }\n\n _hideSizePopover() {\n if (this._sizePopover) this._sizePopover.style.display = 'none';\n this._sizeApply = null;\n }\n}\n","// CodeTooltip.js - Hover tooltip for <pre> code blocks inside the editor\n// Shows a horizontal action bar above (or below) the hovered code block,\n// consistent in appearance and interaction with ImageTooltip / TableTooltip.\nimport { createElement, on } from '../core/dom.js';\n\nconst SHOW_DELAY = 100;\nconst HIDE_DELAY = 180;\n\n// Cached regex for extracting language class — defined once at module level.\nconst _LANG_CLASS_RE = /language-(\\S+)/;\n\nconst ICONS = {\n copy: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`,\n wrapOn: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\"/><path d=\"M3 12h15a3 3 0 0 1 0 6H3\"/><polyline points=\"6 15 3 18 6 21\"/></svg>`,\n toParagraph:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M13 4v16\"/><path d=\"M17 4v16\"/><path d=\"M9 4h8a4 4 0 0 1 0 8H9V4z\"/></svg>`,\n deleteCode: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n};\n\nexport class CodeTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._el = null;\n this._activePre = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n this._copyBtn = null;\n this._langSelect = null;\n this._prismScript = null; // script element while Prism is loading\n }\n\n initialize() {\n this._el = this._buildTooltip();\n document.body.appendChild(this._el);\n this._ensurePrism();\n\n const editable = this.context.layoutInfo.editable;\n\n this._disposers.push(\n on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const pre = e.target.closest('pre');\n if (pre && editable.contains(pre)) {\n this._scheduleShow(pre);\n }\n }),\n on(editable, 'mouseout', (e) => {\n const to = e.relatedTarget;\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n on(document, 'click', (e) => {\n if (this._activePre &&\n !this._activePre.contains(e.target) &&\n !this._el.contains(e.target)) {\n this._hide();\n }\n }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _buildTooltip() {\n const L = this.context.locale.tooltips.code;\n const el = createElement('div', {\n class: 'an-link-tooltip an-code-tooltip',\n role: 'toolbar',\n 'aria-label': L.ariaLabel,\n });\n el.style.display = 'none';\n\n // Label\n this._label = createElement('span', { class: 'an-link-tooltip-url' });\n this._label.textContent = L.label;\n el.appendChild(this._label);\n\n el.appendChild(this._sep());\n\n // Language selector\n this._langSelect = createElement('select', {\n class: 'an-code-lang-select',\n title: L.syntaxLanguage,\n 'aria-label': L.syntaxAriaLabel,\n });\n const LANGUAGES = [\n ['', 'Plain text'], ['javascript', 'JavaScript'], ['typescript', 'TypeScript'],\n ['python', 'Python'], ['html', 'HTML'], ['css', 'CSS'], ['json', 'JSON'],\n ['xml', 'XML'], ['bash', 'Bash / Shell'], ['sql', 'SQL'],\n ['java', 'Java'], ['csharp', 'C#'], ['php', 'PHP'], ['ruby', 'Ruby'],\n ['go', 'Go'], ['rust', 'Rust'], ['cpp', 'C++'], ['c', 'C'],\n ['kotlin', 'Kotlin'], ['swift', 'Swift'],\n ];\n LANGUAGES.forEach(([value, label]) => {\n const opt = createElement('option', { value });\n opt.textContent = label;\n this._langSelect.appendChild(opt);\n });\n this._disposers.push(on(this._langSelect, 'change', () => this._onLangChange()));\n el.appendChild(this._langSelect);\n\n el.appendChild(this._sep());\n\n // Copy code\n this._copyBtn = this._makeBtn(ICONS.copy, L.copyCode, () => this._copyCode());\n\n el.appendChild(this._copyBtn);\n\n el.appendChild(this._sep());\n\n // Toggle word-wrap\n this._wrapBtn = this._makeBtn(ICONS.wrapOn, L.toggleWordWrap, () => this._toggleWrap());\n el.appendChild(this._wrapBtn);\n\n el.appendChild(this._sep());\n\n // Convert to normal paragraph\n el.appendChild(this._makeBtn(ICONS.toParagraph, L.convertToParagraph, () => this._toParagraph()));\n\n el.appendChild(this._sep());\n\n // Delete block\n el.appendChild(this._makeBtn(ICONS.deleteCode, L.deleteCodeBlock, () => this._delete(), true));\n\n // Keep tooltip alive while hovering it\n this._disposers.push(\n on(el, 'mouseenter', () => this._clearTimers()),\n on(el, 'mouseleave', () => this._scheduleHide()),\n );\n\n return el;\n }\n\n _sep() {\n return createElement('div', { class: 'an-link-tooltip-sep' });\n }\n\n /**\n * @param {string} icon\n * @param {string} title\n * @param {Function} handler\n * @param {boolean} [isDanger]\n */\n _makeBtn(icon, title, handler, isDanger = false) {\n const btn = createElement('button', {\n type: 'button',\n class: isDanger ? 'an-link-tooltip-btn an-link-tooltip-btn--danger' : 'an-link-tooltip-btn',\n title,\n });\n btn.innerHTML = icon;\n this._disposers.push(on(btn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // Show / Hide\n // ---------------------------------------------------------------------------\n\n _scheduleShow(pre) {\n if (this._activePre === pre && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._activePre = pre;\n this._syncWrapBtn();\n this._syncLangSelect();\n this._show(pre);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n clearTimeout(this._showTimer);\n this._showTimer = null;\n // Always reset the hide timer so rapid mouseout→mouseover sequences\n // don't leave a stale timer that hides the tooltip prematurely.\n clearTimeout(this._hideTimer);\n this._hideTimer = setTimeout(() => this._hide(), HIDE_DELAY);\n }\n\n _show(pre) {\n this._el.style.display = 'flex';\n this._positionNear(pre);\n }\n\n _hide() {\n this._el.style.display = 'none';\n this._activePre = null;\n this._clearTimers();\n }\n\n _clearTimers() {\n clearTimeout(this._showTimer);\n clearTimeout(this._hideTimer);\n this._showTimer = null;\n this._hideTimer = null;\n }\n\n _positionNear(pre) {\n const rect = pre.getBoundingClientRect();\n const tipW = this._el.offsetWidth || 260;\n const tipH = this._el.offsetHeight || 32;\n const margin = 6;\n\n // Prefer above the block; fall back to below\n let top = rect.top - tipH - margin;\n let left = rect.left + (rect.width - tipW) / 2;\n\n if (top < margin) top = rect.bottom + margin;\n if (left + tipW > window.innerWidth - margin) left = window.innerWidth - tipW - margin;\n if (left < margin) left = margin;\n\n // Tooltip uses position:fixed, so viewport coordinates are used directly.\n this._el.style.top = `${top}px`;\n this._el.style.left = `${left}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Sync wrap-button active state\n // ---------------------------------------------------------------------------\n\n _syncWrapBtn() {\n if (!this._activePre || !this._wrapBtn) return;\n const wrapped = (this._activePre.style.whiteSpace || '').includes('pre-wrap')\n || window.getComputedStyle(this._activePre).whiteSpace === 'pre-wrap';\n this._wrapBtn.classList.toggle('active', wrapped);\n this._wrapBtn.title = wrapped\n ? this.context.locale.tooltips.code.disableWordWrap\n : this.context.locale.tooltips.code.enableWordWrap;\n }\n\n _syncLangSelect() {\n if (!this._activePre || !this._langSelect) return;\n const codeEl = this._activePre.querySelector('code');\n const fromAttr = this._activePre.getAttribute('data-language') || '';\n const fromClass = codeEl ? (_LANG_CLASS_RE.exec(codeEl.className) || [])[1] || '' : '';\n this._langSelect.value = fromAttr || fromClass || '';\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _copyCode() {\n const pre = this._activePre;\n if (!pre) return;\n const text = pre.textContent || '';\n if (navigator.clipboard) {\n navigator.clipboard.writeText(text).then(() => this._flashCopied()).catch(() => {});\n } else {\n // Fallback for older browsers\n const ta = document.createElement('textarea');\n ta.value = text;\n ta.style.cssText = 'position:fixed;opacity:0;top:0;left:0';\n document.body.appendChild(ta);\n ta.select();\n try { document.execCommand('copy'); this._flashCopied(); } catch (_) {}\n document.body.removeChild(ta);\n }\n }\n\n _flashCopied() {\n if (!this._copyBtn) return;\n const original = this._copyBtn.innerHTML;\n this._copyBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n this._copyBtn.classList.add('an-link-tooltip-btn--copied');\n setTimeout(() => {\n if (this._copyBtn) {\n this._copyBtn.innerHTML = original;\n this._copyBtn.classList.remove('an-link-tooltip-btn--copied');\n }\n }, 1400);\n }\n\n _toggleWrap() {\n const pre = this._activePre;\n if (!pre) return;\n const isWrapped = pre.style.whiteSpace === 'pre-wrap';\n pre.style.whiteSpace = isWrapped ? 'pre' : 'pre-wrap';\n this._syncWrapBtn();\n this.context.invoke('editor.afterCommand');\n this._positionNear(pre);\n }\n\n _onLangChange() {\n const pre = this._activePre;\n if (!pre) return;\n const lang = this._langSelect.value;\n\n // Ensure a <code> child exists (Prism targets <pre><code class=\"language-xxx\">)\n let codeEl = pre.querySelector('code');\n if (!codeEl) {\n codeEl = document.createElement('code');\n codeEl.innerHTML = pre.innerHTML;\n pre.innerHTML = '';\n pre.appendChild(codeEl);\n }\n\n codeEl.className = lang ? `language-${lang}` : '';\n // Mirror language class on <pre> so Prism CSS theme targets it (pre[class*='language-'])\n pre.className = lang ? `language-${lang}` : '';\n if (lang) {\n pre.setAttribute('data-language', lang);\n } else {\n pre.removeAttribute('data-language');\n }\n\n // Trigger Prism if available.\n // contenteditable stores line breaks as <br> elements; Prism reads textContent\n // which drops <br> entirely, collapsing all lines into one. Convert first.\n const applyPrism = () => {\n codeEl.querySelectorAll('br').forEach((br) => br.replaceWith('\\n'));\n window.Prism.highlightElement(codeEl);\n this.context.invoke('editor.afterCommand');\n };\n\n if (lang) {\n if (typeof window.Prism !== 'undefined') {\n // Grammar already loaded — highlight immediately\n if (window.Prism.languages[lang]) {\n applyPrism();\n return;\n }\n // Grammar not in core bundle — load the component script first\n this._loadPrismComponent(lang, applyPrism);\n return;\n } else if (this._prismScript) {\n // Prism core is still loading — highlight once it arrives, then load grammar if needed\n this._prismScript.addEventListener('load', () => {\n if (window.Prism.languages[lang]) {\n applyPrism();\n } else {\n this._loadPrismComponent(lang, applyPrism);\n }\n }, { once: true });\n return;\n }\n }\n\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Loads Prism.js + CSS from CDN when options.codeHighlight is true.\n * Called once at initialize time. Fire-and-forget; errors are silent.\n */\n _ensurePrism() {\n if (!this.context.options.codeHighlight || window.Prism) return;\n const cdn = this.context.options.codeHighlightCDN;\n const themeHref = `${cdn}/themes/prism-tomorrow.min.css`;\n const scriptSrc = `${cdn}/prism.min.js`;\n\n if (!document.querySelector(`link[href=\"${themeHref}\"]`)) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = themeHref;\n document.head.appendChild(link);\n }\n\n const existingScript = document.querySelector(`script[src=\"${scriptSrc}\"]`);\n if (existingScript) {\n this._prismScript = window.Prism ? null : existingScript;\n return;\n }\n\n const script = document.createElement('script');\n script.dataset.manual = ''; // prevent auto-highlight on load\n script.src = scriptSrc;\n this._prismScript = script;\n script.addEventListener('load', () => { this._prismScript = null; }, { once: true });\n document.head.appendChild(script);\n }\n\n /**\n * Dynamically loads a Prism language component script if not already available.\n * Prism core only bundles: markup, css, clike, javascript.\n * All other grammars (bash, python, etc.) need a component file.\n * @param {string} lang – Prism language slug (e.g. 'bash', 'python')\n * @param {Function} cb – called once the grammar is ready\n */\n _loadPrismComponent(lang, cb) {\n const cdn = this.context.options.codeHighlightCDN;\n const src = `${cdn}/components/prism-${lang}.min.js`;\n // Avoid loading the same component twice\n if (document.querySelector(`script[src=\"${src}\"]`)) {\n // Already in DOM — might still be loading; poll briefly then call cb\n const poll = setInterval(() => {\n if (window.Prism && window.Prism.languages[lang]) {\n clearInterval(poll);\n cb();\n }\n }, 50);\n setTimeout(() => clearInterval(poll), 3000); // give up after 3s\n return;\n }\n const s = document.createElement('script');\n s.src = src;\n s.addEventListener('load', cb, { once: true });\n document.head.appendChild(s);\n }\n\n _toParagraph() {\n const pre = this._activePre;\n if (!pre) return;\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n\n // Replace <pre> with <p> preserving lines as <br>\n const lines = (pre.textContent || '').split('\\n');\n const p = document.createElement('p');\n lines.forEach((line, i) => {\n if (i > 0) p.appendChild(document.createElement('br'));\n p.appendChild(document.createTextNode(line));\n });\n\n pre.parentNode.replaceChild(p, pre);\n this._hide();\n this.context.invoke('editor.afterCommand');\n }\n\n _delete() {\n const pre = this._activePre;\n if (!pre) return;\n this._hide();\n if (pre.parentNode) pre.parentNode.removeChild(pre);\n this.context.invoke('editor.afterCommand');\n }\n}\n","/**\n * EmojiDialog.js - Browse and insert Unicode emoji / symbols (UTF-8 / utf8mb4)\n * Click an emoji to insert it directly at the caret — no extra \"Insert\" step.\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// Emoji catalogue\n// ---------------------------------------------------------------------------\n\nconst EMOJI_CATS = [\n { id: 'smileys', label: 'Smileys' },\n { id: 'people', label: 'People' },\n { id: 'animals', label: 'Animals' },\n { id: 'food', label: 'Food' },\n { id: 'travel', label: 'Travel' },\n { id: 'objects', label: 'Objects' },\n { id: 'symbols', label: 'Symbols' },\n];\n\n// [emoji_char, search_keywords, category]\nconst EMOJI_LIST = [\n // Smileys & Emotions\n ['😀', 'grin smile happy face', 'smileys'],\n ['😃', 'happy smile big eyes', 'smileys'],\n ['😄', 'grinning smile laugh', 'smileys'],\n ['😁', 'beaming smile grin', 'smileys'],\n ['😆', 'laughing lol', 'smileys'],\n ['😅', 'sweat grin awkward', 'smileys'],\n ['🤣', 'rolling laugh rofl', 'smileys'],\n ['😂', 'tears laugh cry joy', 'smileys'],\n ['🙂', 'slight smile', 'smileys'],\n ['🙃', 'upside down smile', 'smileys'],\n ['😉', 'wink', 'smileys'],\n ['😊', 'blush smile happy', 'smileys'],\n ['😇', 'innocent halo angel', 'smileys'],\n ['🥰', 'hearts love adore', 'smileys'],\n ['😍', 'heart eyes love', 'smileys'],\n ['🤩', 'star eyes excited wow', 'smileys'],\n ['😘', 'kiss blow love', 'smileys'],\n ['😋', 'yum delicious tongue', 'smileys'],\n ['😛', 'tongue stuck out', 'smileys'],\n ['😜', 'wink tongue crazy', 'smileys'],\n ['🤪', 'zany crazy wild', 'smileys'],\n ['😝', 'squint tongue', 'smileys'],\n ['🤑', 'money mouth', 'smileys'],\n ['🤗', 'hugging hug', 'smileys'],\n ['🤔', 'thinking hmm', 'smileys'],\n ['🤨', 'raised eyebrow', 'smileys'],\n ['😐', 'neutral face', 'smileys'],\n ['😶', 'no mouth', 'smileys'],\n ['😏', 'smirk', 'smileys'],\n ['😒', 'unamused', 'smileys'],\n ['🙄', 'roll eyes', 'smileys'],\n ['😬', 'grimace', 'smileys'],\n ['😔', 'pensive sad', 'smileys'],\n ['😪', 'sleepy tired', 'smileys'],\n ['😴', 'sleeping zzz', 'smileys'],\n ['🤤', 'drool', 'smileys'],\n ['😷', 'mask sick', 'smileys'],\n ['🤒', 'sick thermometer', 'smileys'],\n ['🤕', 'hurt bandage', 'smileys'],\n ['🤢', 'nausea sick', 'smileys'],\n ['🤮', 'vomit sick', 'smileys'],\n ['🤧', 'sneeze cold', 'smileys'],\n ['🥵', 'hot sweat', 'smileys'],\n ['🥶', 'cold freeze', 'smileys'],\n ['😵', 'dizzy dead', 'smileys'],\n ['🤯', 'mind blown', 'smileys'],\n ['🤠', 'cowboy hat', 'smileys'],\n ['🥳', 'party celebrate', 'smileys'],\n ['😎', 'cool sunglasses', 'smileys'],\n ['🤓', 'nerd glasses', 'smileys'],\n ['🧐', 'monocle curious', 'smileys'],\n ['😕', 'confused', 'smileys'],\n ['😟', 'worried', 'smileys'],\n ['🙁', 'frown sad', 'smileys'],\n ['☹️', 'sad frown', 'smileys'],\n ['😮', 'surprised open mouth', 'smileys'],\n ['😲', 'astonished', 'smileys'],\n ['🥺', 'pleading begging puppy eyes', 'smileys'],\n ['😢', 'cry sad tear', 'smileys'],\n ['😭', 'sob cry loudly', 'smileys'],\n ['😱', 'scream horror fear', 'smileys'],\n ['😡', 'angry red pouting', 'smileys'],\n ['😠', 'angry mad', 'smileys'],\n ['🤬', 'cursing swear', 'smileys'],\n ['😈', 'devil evil smile', 'smileys'],\n ['👿', 'devil angry evil', 'smileys'],\n ['💀', 'skull death', 'smileys'],\n ['☠️', 'skull crossbones', 'smileys'],\n ['💩', 'poop', 'smileys'],\n ['🤡', 'clown', 'smileys'],\n ['👻', 'ghost boo', 'smileys'],\n ['👽', 'alien ufo', 'smileys'],\n ['🤖', 'robot', 'smileys'],\n\n // People & Body\n ['👋', 'wave hello hi hand', 'people'],\n ['🤚', 'raised back hand', 'people'],\n ['✋', 'raised hand stop', 'people'],\n ['🖖', 'vulcan salute spock', 'people'],\n ['👌', 'ok perfect fine', 'people'],\n ['✌️', 'peace victory fingers', 'people'],\n ['🤞', 'fingers crossed luck', 'people'],\n ['🤟', 'love you gesture', 'people'],\n ['🤘', 'sign of horns rock', 'people'],\n ['🤙', 'call me hand', 'people'],\n ['👈', 'point left', 'people'],\n ['👉', 'point right', 'people'],\n ['👆', 'point up', 'people'],\n ['👇', 'point down', 'people'],\n ['☝️', 'index pointing up', 'people'],\n ['👍', 'thumbs up like good', 'people'],\n ['👎', 'thumbs down dislike bad', 'people'],\n ['✊', 'raised fist punch', 'people'],\n ['👊', 'oncoming fist punch', 'people'],\n ['👏', 'clap applause', 'people'],\n ['🙌', 'celebrate raise hands', 'people'],\n ['🤝', 'handshake deal', 'people'],\n ['🙏', 'pray hope please thanks', 'people'],\n ['💅', 'nail polish', 'people'],\n ['💪', 'flexed bicep strong muscle', 'people'],\n ['👀', 'eyes look see', 'people'],\n ['👁️', 'eye', 'people'],\n ['👅', 'tongue', 'people'],\n ['👶', 'baby', 'people'],\n ['🧒', 'child', 'people'],\n ['👦', 'boy', 'people'],\n ['👧', 'girl', 'people'],\n ['🧑', 'person adult', 'people'],\n ['👨', 'man', 'people'],\n ['👩', 'woman', 'people'],\n ['🧔', 'beard man', 'people'],\n ['🧓', 'older person', 'people'],\n ['👴', 'old man', 'people'],\n ['👵', 'old woman', 'people'],\n ['❤️', 'heart love red', 'people'],\n ['🧡', 'orange heart love', 'people'],\n ['💛', 'yellow heart love', 'people'],\n ['💚', 'green heart love', 'people'],\n ['💙', 'blue heart love', 'people'],\n ['💜', 'purple heart love', 'people'],\n ['🖤', 'black heart', 'people'],\n ['🤍', 'white heart', 'people'],\n ['🤎', 'brown heart', 'people'],\n ['💔', 'broken heart', 'people'],\n ['❣️', 'exclamation heart', 'people'],\n ['💕', 'two hearts love', 'people'],\n ['💞', 'revolving hearts', 'people'],\n ['💓', 'beating heart', 'people'],\n ['💗', 'growing heart', 'people'],\n ['💖', 'sparkling heart', 'people'],\n ['💘', 'heart arrow', 'people'],\n ['💝', 'heart ribbon', 'people'],\n ['💬', 'speech bubble comment chat', 'people'],\n ['💭', 'thought bubble', 'people'],\n ['💯', '100 hundred percent perfect', 'people'],\n ['💢', 'anger symbol mad', 'people'],\n ['💤', 'zzz sleep', 'people'],\n\n // Animals & Nature\n ['🐶', 'dog puppy', 'animals'],\n ['🐱', 'cat kitten', 'animals'],\n ['🐭', 'mouse', 'animals'],\n ['🐹', 'hamster', 'animals'],\n ['🐰', 'rabbit bunny', 'animals'],\n ['🦊', 'fox', 'animals'],\n ['🐻', 'bear', 'animals'],\n ['🐼', 'panda', 'animals'],\n ['🐨', 'koala', 'animals'],\n ['🐯', 'tiger', 'animals'],\n ['🦁', 'lion', 'animals'],\n ['🐮', 'cow', 'animals'],\n ['🐷', 'pig', 'animals'],\n ['🐸', 'frog', 'animals'],\n ['🐵', 'monkey', 'animals'],\n ['🙈', 'see no evil monkey', 'animals'],\n ['🙉', 'hear no evil monkey', 'animals'],\n ['🙊', 'speak no evil monkey', 'animals'],\n ['🐔', 'chicken hen', 'animals'],\n ['🐧', 'penguin', 'animals'],\n ['🐦', 'bird', 'animals'],\n ['🦆', 'duck', 'animals'],\n ['🦅', 'eagle', 'animals'],\n ['🦉', 'owl', 'animals'],\n ['🦇', 'bat', 'animals'],\n ['🐺', 'wolf', 'animals'],\n ['🐴', 'horse', 'animals'],\n ['🦄', 'unicorn', 'animals'],\n ['🐝', 'bee', 'animals'],\n ['🦋', 'butterfly', 'animals'],\n ['🐌', 'snail', 'animals'],\n ['🐞', 'ladybug', 'animals'],\n ['🐢', 'turtle', 'animals'],\n ['🐍', 'snake', 'animals'],\n ['🦎', 'lizard', 'animals'],\n ['🐊', 'crocodile', 'animals'],\n ['🐟', 'fish', 'animals'],\n ['🐠', 'tropical fish', 'animals'],\n ['🦈', 'shark', 'animals'],\n ['🐬', 'dolphin', 'animals'],\n ['🐳', 'whale', 'animals'],\n ['🐙', 'octopus', 'animals'],\n ['🦑', 'squid', 'animals'],\n ['🦀', 'crab', 'animals'],\n ['🌸', 'cherry blossom flower', 'animals'],\n ['🌺', 'hibiscus flower', 'animals'],\n ['🌻', 'sunflower', 'animals'],\n ['🌹', 'rose flower', 'animals'],\n ['🌷', 'tulip flower', 'animals'],\n ['🍀', 'four leaf clover luck', 'animals'],\n ['🌿', 'herb leaf green', 'animals'],\n ['🌱', 'seedling sprout', 'animals'],\n ['🌲', 'evergreen tree pine', 'animals'],\n ['🌳', 'deciduous tree', 'animals'],\n ['🌴', 'palm tree', 'animals'],\n ['🍄', 'mushroom', 'animals'],\n ['🌾', 'sheaf wheat', 'animals'],\n ['🐾', 'paw prints animal', 'animals'],\n\n // Food & Drink\n ['🍎', 'apple red', 'food'],\n ['🍊', 'orange tangerine', 'food'],\n ['🍋', 'lemon yellow', 'food'],\n ['🍇', 'grapes', 'food'],\n ['🍓', 'strawberry', 'food'],\n ['🫐', 'blueberry', 'food'],\n ['🍒', 'cherry', 'food'],\n ['🍑', 'peach', 'food'],\n ['🥭', 'mango', 'food'],\n ['🍍', 'pineapple', 'food'],\n ['🥥', 'coconut', 'food'],\n ['🥝', 'kiwi', 'food'],\n ['🍅', 'tomato', 'food'],\n ['🥑', 'avocado', 'food'],\n ['🍆', 'eggplant aubergine', 'food'],\n ['🥕', 'carrot', 'food'],\n ['🌽', 'corn', 'food'],\n ['🥦', 'broccoli', 'food'],\n ['🥬', 'leafy green', 'food'],\n ['🧄', 'garlic', 'food'],\n ['🥜', 'peanut nut', 'food'],\n ['🍞', 'bread loaf', 'food'],\n ['🥐', 'croissant', 'food'],\n ['🧀', 'cheese', 'food'],\n ['🍳', 'egg fry cooking', 'food'],\n ['🥚', 'egg', 'food'],\n ['🥞', 'pancake', 'food'],\n ['🧇', 'waffle', 'food'],\n ['🥓', 'bacon', 'food'],\n ['🥩', 'meat steak', 'food'],\n ['🍗', 'chicken leg', 'food'],\n ['🌭', 'hotdog', 'food'],\n ['🍔', 'burger hamburger', 'food'],\n ['🍟', 'fries french', 'food'],\n ['🍕', 'pizza', 'food'],\n ['🌮', 'taco', 'food'],\n ['🌯', 'burrito wrap', 'food'],\n ['🍜', 'noodles ramen', 'food'],\n ['🍝', 'spaghetti pasta', 'food'],\n ['🍣', 'sushi', 'food'],\n ['🍱', 'bento box', 'food'],\n ['🍦', 'ice cream soft serve', 'food'],\n ['🍩', 'donut', 'food'],\n ['🍪', 'cookie', 'food'],\n ['🎂', 'birthday cake', 'food'],\n ['🍰', 'cake slice', 'food'],\n ['🧁', 'cupcake', 'food'],\n ['🍫', 'chocolate', 'food'],\n ['🍬', 'candy', 'food'],\n ['🍭', 'lollipop', 'food'],\n ['☕', 'coffee hot', 'food'],\n ['🍵', 'tea hot', 'food'],\n ['🧋', 'bubble tea boba', 'food'],\n ['🥤', 'cup straw drink', 'food'],\n ['🍷', 'wine red', 'food'],\n ['🍸', 'cocktail martini', 'food'],\n ['🍺', 'beer mug', 'food'],\n ['🍻', 'clinking beer mugs', 'food'],\n ['🥂', 'champagne toast celebrate', 'food'],\n ['🧃', 'juice box', 'food'],\n ['🧊', 'ice cube', 'food'],\n\n // Travel & Places\n ['🚀', 'rocket space', 'travel'],\n ['🛸', 'ufo flying saucer', 'travel'],\n ['✈️', 'airplane plane fly', 'travel'],\n ['🚁', 'helicopter', 'travel'],\n ['🚂', 'train locomotive', 'travel'],\n ['🚄', 'bullet train fast', 'travel'],\n ['🚇', 'subway metro', 'travel'],\n ['🚌', 'bus', 'travel'],\n ['🚑', 'ambulance', 'travel'],\n ['🚒', 'fire truck', 'travel'],\n ['🚓', 'police car', 'travel'],\n ['🚕', 'taxi cab', 'travel'],\n ['🚗', 'car automobile red', 'travel'],\n ['🚙', 'suv car', 'travel'],\n ['🚚', 'truck delivery', 'travel'],\n ['🚜', 'tractor farm', 'travel'],\n ['🏎️', 'racing car fast', 'travel'],\n ['🏍️', 'motorcycle', 'travel'],\n ['🚲', 'bicycle bike', 'travel'],\n ['🛴', 'scooter kick', 'travel'],\n ['⛵', 'sailboat boat', 'travel'],\n ['🚢', 'ship cruise', 'travel'],\n ['🏠', 'house home', 'travel'],\n ['🏢', 'office building', 'travel'],\n ['🏥', 'hospital', 'travel'],\n ['🏦', 'bank', 'travel'],\n ['🏪', 'store shop convenience', 'travel'],\n ['🏫', 'school', 'travel'],\n ['🏰', 'castle european', 'travel'],\n ['🏯', 'japanese castle', 'travel'],\n ['🗼', 'tokyo tower', 'travel'],\n ['🗽', 'statue liberty new york', 'travel'],\n ['⛪', 'church', 'travel'],\n ['🕌', 'mosque', 'travel'],\n ['⛩️', 'shinto shrine', 'travel'],\n ['⛲', 'fountain', 'travel'],\n ['⛺', 'tent camping', 'travel'],\n ['🌁', 'fog foggy bridge', 'travel'],\n ['🌃', 'night city stars', 'travel'],\n ['🏙️', 'cityscape city buildings', 'travel'],\n ['🌅', 'sunrise morning', 'travel'],\n ['🌈', 'rainbow colorful', 'travel'],\n ['⛰️', 'mountain', 'travel'],\n ['🏔️', 'snow mountain', 'travel'],\n ['🗻', 'mount fuji', 'travel'],\n ['🏕️', 'camping tent', 'travel'],\n ['🗺️', 'world map', 'travel'],\n ['🧭', 'compass navigation', 'travel'],\n ['🌍', 'earth europe africa globe', 'travel'],\n ['🌎', 'earth americas globe', 'travel'],\n ['🌏', 'earth asia globe', 'travel'],\n ['🌐', 'globe internet web', 'travel'],\n\n // Objects\n ['💎', 'diamond gem jewel', 'objects'],\n ['💍', 'ring engagement', 'objects'],\n ['👑', 'crown royal king queen', 'objects'],\n ['🎩', 'top hat magic', 'objects'],\n ['💼', 'briefcase work business', 'objects'],\n ['👜', 'handbag purse', 'objects'],\n ['🎒', 'backpack bag school', 'objects'],\n ['👓', 'glasses eyewear', 'objects'],\n ['🕶️', 'sunglasses cool', 'objects'],\n ['💡', 'light bulb idea', 'objects'],\n ['🔦', 'flashlight torch', 'objects'],\n ['🕯️', 'candle light', 'objects'],\n ['🔋', 'battery charge', 'objects'],\n ['💻', 'laptop computer', 'objects'],\n ['🖥️', 'desktop monitor computer', 'objects'],\n ['📱', 'phone mobile cell', 'objects'],\n ['⌨️', 'keyboard type', 'objects'],\n ['🖱️', 'mouse computer click', 'objects'],\n ['📺', 'television tv', 'objects'],\n ['📷', 'camera photo', 'objects'],\n ['📹', 'video camera', 'objects'],\n ['🎥', 'movie camera film', 'objects'],\n ['☎️', 'telephone phone', 'objects'],\n ['⏰', 'alarm clock wake', 'objects'],\n ['⌚', 'watch time', 'objects'],\n ['🔑', 'key', 'objects'],\n ['🗝️', 'old key', 'objects'],\n ['🔒', 'lock closed', 'objects'],\n ['🔓', 'unlock open', 'objects'],\n ['🔨', 'hammer tool', 'objects'],\n ['🔧', 'wrench tool', 'objects'],\n ['🔩', 'bolt nut', 'objects'],\n ['⚙️', 'gear setting', 'objects'],\n ['🧲', 'magnet attract', 'objects'],\n ['📚', 'books stack library', 'objects'],\n ['📖', 'book open read', 'objects'],\n ['📝', 'memo write note', 'objects'],\n ['✏️', 'pencil write edit', 'objects'],\n ['📌', 'pushpin tack', 'objects'],\n ['📎', 'paperclip attach', 'objects'],\n ['📊', 'bar chart graph', 'objects'],\n ['📈', 'chart up growth trend', 'objects'],\n ['📉', 'chart down loss decline', 'objects'],\n ['📅', 'calendar date', 'objects'],\n ['📦', 'package box', 'objects'],\n ['📫', 'mailbox closed', 'objects'],\n ['📧', 'email envelope', 'objects'],\n ['🎁', 'gift present', 'objects'],\n ['🎀', 'ribbon bow', 'objects'],\n ['🎉', 'party celebrate confetti', 'objects'],\n ['🎊', 'confetti celebrate', 'objects'],\n ['🔮', 'crystal ball magic fortune', 'objects'],\n ['🪄', 'magic wand', 'objects'],\n ['🎯', 'target bullseye dart', 'objects'],\n ['🎲', 'dice game board', 'objects'],\n ['🎮', 'video game controller', 'objects'],\n ['🎭', 'theater masks drama', 'objects'],\n ['🎨', 'art palette paint', 'objects'],\n ['🎬', 'clapper film movie', 'objects'],\n ['🎤', 'microphone sing karaoke', 'objects'],\n ['🎧', 'headphones music listen', 'objects'],\n ['🎵', 'music note', 'objects'],\n ['🎶', 'music notes', 'objects'],\n ['🎸', 'guitar electric', 'objects'],\n ['🎹', 'piano keyboard music', 'objects'],\n ['🥁', 'drum percussion', 'objects'],\n ['🎷', 'saxophone jazz', 'objects'],\n ['🎺', 'trumpet', 'objects'],\n ['🎻', 'violin', 'objects'],\n ['⚽', 'soccer ball football', 'objects'],\n ['🏀', 'basketball', 'objects'],\n ['🏈', 'american football', 'objects'],\n ['⚾', 'baseball', 'objects'],\n ['🎾', 'tennis', 'objects'],\n ['🏐', 'volleyball', 'objects'],\n ['🏆', 'trophy winner award', 'objects'],\n ['🥇', 'gold medal first', 'objects'],\n ['🏅', 'sports medal', 'objects'],\n\n // Symbols\n ['✅', 'check green done success', 'symbols'],\n ['❌', 'cross x no cancel', 'symbols'],\n ['⭕', 'circle red', 'symbols'],\n ['⛔', 'no entry stop', 'symbols'],\n ['🚫', 'prohibited no banned', 'symbols'],\n ['⚠️', 'warning caution danger', 'symbols'],\n ['❗', 'exclamation red important', 'symbols'],\n ['❓', 'question mark', 'symbols'],\n ['‼️', 'double exclamation', 'symbols'],\n ['💯', '100 hundred percent perfect', 'symbols'],\n ['🔴', 'red circle dot', 'symbols'],\n ['🟠', 'orange circle', 'symbols'],\n ['🟡', 'yellow circle', 'symbols'],\n ['🟢', 'green circle', 'symbols'],\n ['🔵', 'blue circle', 'symbols'],\n ['🟣', 'purple circle', 'symbols'],\n ['⚫', 'black circle', 'symbols'],\n ['⚪', 'white circle', 'symbols'],\n ['🟤', 'brown circle', 'symbols'],\n ['🔺', 'red triangle up', 'symbols'],\n ['🔻', 'red triangle down', 'symbols'],\n ['🔷', 'blue diamond large', 'symbols'],\n ['🔶', 'orange diamond large', 'symbols'],\n ['🔹', 'blue diamond small', 'symbols'],\n ['🔸', 'orange diamond small', 'symbols'],\n ['⭐', 'star yellow', 'symbols'],\n ['🌟', 'glowing star shine', 'symbols'],\n ['✨', 'sparkles shine', 'symbols'],\n ['💫', 'dizzy star spin', 'symbols'],\n ['⚡', 'lightning bolt energy power', 'symbols'],\n ['🔥', 'fire hot flame', 'symbols'],\n ['💥', 'explosion boom', 'symbols'],\n ['❄️', 'snowflake cold ice winter', 'symbols'],\n ['🌊', 'wave water ocean sea', 'symbols'],\n ['💨', 'wind blow dash', 'symbols'],\n ['🌀', 'cyclone tornado spiral', 'symbols'],\n ['♻️', 'recycle loop green', 'symbols'],\n ['✔️', 'check tick done', 'symbols'],\n ['➕', 'plus add', 'symbols'],\n ['➖', 'minus subtract', 'symbols'],\n ['➗', 'divide division', 'symbols'],\n ['✖️', 'multiply times cross', 'symbols'],\n ['▶️', 'play button right', 'symbols'],\n ['⏸️', 'pause', 'symbols'],\n ['⏹️', 'stop square', 'symbols'],\n ['⏩', 'fast forward', 'symbols'],\n ['⏪', 'rewind fast backward', 'symbols'],\n ['🔔', 'bell notification', 'symbols'],\n ['🔕', 'bell slash mute', 'symbols'],\n ['🔊', 'speaker volume high', 'symbols'],\n ['🔇', 'mute silent no sound', 'symbols'],\n ['📢', 'loudspeaker announcement', 'symbols'],\n ['📣', 'megaphone cheer', 'symbols'],\n ['🏳️', 'white flag', 'symbols'],\n ['🏴', 'black flag', 'symbols'],\n ['🚩', 'red flag', 'symbols'],\n ['🏁', 'checkered flag finish race', 'symbols'],\n ['🆕', 'new badge', 'symbols'],\n ['🆓', 'free badge', 'symbols'],\n ['🆒', 'cool badge', 'symbols'],\n ['🔝', 'top arrow', 'symbols'],\n ['🔙', 'back arrow', 'symbols'],\n ['ℹ️', 'information info', 'symbols'],\n ['📍', 'pin location map', 'symbols'],\n ['🔗', 'link chain', 'symbols'],\n ['©️', 'copyright', 'symbols'],\n ['®️', 'registered trademark', 'symbols'],\n ['™️', 'trademark', 'symbols'],\n ['#️⃣', 'hash number', 'symbols'],\n ['0️⃣', 'zero number', 'symbols'],\n ['1️⃣', 'one number', 'symbols'],\n ['2️⃣', 'two number', 'symbols'],\n ['3️⃣', 'three number', 'symbols'],\n ['4️⃣', 'four number', 'symbols'],\n ['5️⃣', 'five number', 'symbols'],\n];\n\n// ---------------------------------------------------------------------------\n// Dialog class\n// ---------------------------------------------------------------------------\n\nexport class EmojiDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n this._activeCat = 'all';\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n // Dialog grid is built lazily on first show() to avoid rendering ~500 DOM nodes at load time.\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n if (!this._dialog) {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._activeCat = 'all';\n this._searchInput.value = '';\n this._updateCatTabs();\n this._filterEmojis('', 'all');\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.emojiDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box an-emoji-box' });\n\n // Title row\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '×';\n titleRow.append(title, closeBtn);\n\n // Search\n const searchInput = createElement('input', {\n type: 'search',\n class: 'an-input an-icon-search',\n placeholder: L.searchPlaceholder,\n autocomplete: 'off',\n });\n this._searchInput = searchInput;\n\n // Category tabs\n const catBar = createElement('div', { class: 'an-icon-cats' });\n const allTab = createElement('button', { type: 'button', class: 'an-icon-cat active', 'data-cat': 'all' });\n allTab.textContent = L.all;\n catBar.appendChild(allTab);\n EMOJI_CATS.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = (L.categories && L.categories[id]) || label;\n catBar.appendChild(tab);\n });\n this._catBar = catBar;\n\n // Emoji grid — one button per emoji, click = immediate insert\n const grid = createElement('div', { class: 'an-emoji-grid' });\n EMOJI_LIST.forEach(([char, keywords, cat]) => {\n const cell = createElement('button', {\n type: 'button',\n class: 'an-emoji-cell',\n 'data-char': char,\n 'data-keywords': keywords,\n 'data-cat': cat,\n title: keywords.split(' ').slice(0, 2).join(' '),\n });\n cell.textContent = char;\n grid.appendChild(cell);\n });\n this._grid = grid;\n\n // Cancel only — clicking an emoji inserts immediately\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.appendChild(cancelBtn);\n\n box.append(titleRow, searchInput, catBar, grid, btnRow);\n overlay.appendChild(box);\n\n // Events\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d4 = on(searchInput, 'input', () => this._filterEmojis(searchInput.value, this._activeCat));\n const d5 = on(catBar, 'click', (e) => {\n const tab = e.target.closest('[data-cat]');\n if (tab) {\n this._activeCat = tab.dataset.cat;\n this._updateCatTabs();\n this._filterEmojis(this._searchInput.value, this._activeCat);\n }\n });\n const d6 = on(grid, 'click', (e) => {\n const cell = e.target.closest('.an-emoji-cell');\n if (cell) this._onEmojiClick(cell.dataset.char);\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6);\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Filter\n // ---------------------------------------------------------------------------\n\n _updateCatTabs() {\n this._catBar.querySelectorAll('.an-icon-cat').forEach((tab) => {\n tab.classList.toggle('active', tab.dataset.cat === this._activeCat);\n });\n }\n\n _filterEmojis(query, cat) {\n const q = (query || '').trim().toLowerCase();\n let count = 0;\n this._grid.querySelectorAll('.an-emoji-cell').forEach((cell) => {\n const matchCat = !cat || cat === 'all' || cell.dataset.cat === cat;\n const matchQuery = !q || cell.dataset.keywords.includes(q) || cell.dataset.char === q;\n const visible = matchCat && matchQuery;\n cell.style.display = visible ? '' : 'none';\n if (visible) count++;\n });\n let empty = this._grid.querySelector('.an-icon-empty');\n if (!empty) {\n empty = createElement('div', { class: 'an-icon-empty' });\n empty.textContent = 'No emojis found';\n this._grid.appendChild(empty);\n }\n empty.style.display = count > 0 ? 'none' : '';\n }\n\n // ---------------------------------------------------------------------------\n // Insert\n // ---------------------------------------------------------------------------\n\n _onEmojiClick(char) {\n const savedRange = this._savedRange;\n const editable = this.context.layoutInfo.editable;\n\n // 1. Restore selection while dialog is still mounted (same pattern as ImageDialog)\n if (savedRange) savedRange.select();\n\n const sel = window.getSelection();\n let range = sel && sel.rangeCount > 0 ? sel.getRangeAt(0) : null;\n if (!range) {\n range = document.createRange();\n range.selectNodeContents(editable);\n range.collapse(false);\n }\n\n // 2. Insert emoji as a plain text node — no ZWS or execCommand needed.\n // Text nodes are natively navigable so the caret lands cleanly after.\n //\n // E-1: When the range covers the entire content of a <td>/<th>,\n // deleteContents() can drift the range endpoint outside the cell in some\n // browsers. Save the cell reference first and re-anchor after deletion.\n const _sc = range.startContainer;\n const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest?.('td, th');\n range.deleteContents();\n if (_tdAnchor && _tdAnchor.isConnected && !_tdAnchor.contains(range.startContainer)) {\n range.setStart(_tdAnchor, 0);\n range.collapse(true);\n }\n const textNode = document.createTextNode(char);\n range.insertNode(textNode);\n\n // 3. Place caret immediately after the emoji character\n range.setStartAfter(textNode);\n range.collapse(true);\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n // 4. Close and restore editor focus\n this._close();\n editable.focus();\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Open / Close\n // ---------------------------------------------------------------------------\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._searchInput && this._searchInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n }\n}\n","/**\n * IconDialog.js - Browse and insert FontAwesome Free icons\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\n// ---------------------------------------------------------------------------\n// Icon catalogue — FA 6 Free Solid slug names, grouped by category\n// ---------------------------------------------------------------------------\n\nconst ICON_CATEGORIES = [\n { id: 'popular', label: 'Popular' },\n { id: 'interface', label: 'Interface' },\n { id: 'navigation', label: 'Navigation' },\n { id: 'media', label: 'Media' },\n { id: 'communication', label: 'Communication' },\n { id: 'files', label: 'Files' },\n { id: 'people', label: 'People' },\n { id: 'objects', label: 'Objects' },\n];\n\n// Each entry: [slug, category]\nconst ICON_LIST = [\n // Popular\n ['house', 'popular'],\n ['star', 'popular'],\n ['heart', 'popular'],\n ['check', 'popular'],\n ['xmark', 'popular'],\n ['plus', 'popular'],\n ['minus', 'popular'],\n ['magnifying-glass', 'popular'],\n ['gear', 'popular'],\n ['bell', 'popular'],\n ['user', 'popular'],\n ['envelope', 'popular'],\n ['phone', 'popular'],\n ['calendar', 'popular'],\n ['clock', 'popular'],\n ['lock', 'popular'],\n ['eye', 'popular'],\n ['eye-slash', 'popular'],\n ['trash', 'popular'],\n ['pen', 'popular'],\n ['bookmark', 'popular'],\n ['flag', 'popular'],\n ['thumbs-up', 'popular'],\n ['thumbs-down', 'popular'],\n ['circle-info', 'popular'],\n ['triangle-exclamation', 'popular'],\n ['circle-check', 'popular'],\n ['circle-xmark', 'popular'],\n ['share', 'popular'],\n ['download', 'popular'],\n ['upload', 'popular'],\n ['tag', 'popular'],\n // Interface\n ['bars', 'interface'],\n ['ellipsis', 'interface'],\n ['ellipsis-vertical', 'interface'],\n ['list', 'interface'],\n ['table-cells', 'interface'],\n ['table-list', 'interface'],\n ['grip', 'interface'],\n ['filter', 'interface'],\n ['sort', 'interface'],\n ['arrows-rotate', 'interface'],\n ['rotate', 'interface'],\n ['rotate-left', 'interface'],\n ['rotate-right', 'interface'],\n ['copy', 'interface'],\n ['floppy-disk', 'interface'],\n ['print', 'interface'],\n ['link', 'interface'],\n ['code', 'interface'],\n ['expand', 'interface'],\n ['compress', 'interface'],\n ['cloud', 'interface'],\n ['lock-open', 'interface'],\n ['key', 'interface'],\n ['shield', 'interface'],\n ['shield-halved', 'interface'],\n ['sliders', 'interface'],\n ['toggle-on', 'interface'],\n ['square-check', 'interface'],\n ['circle-plus', 'interface'],\n ['circle-minus', 'interface'],\n // Navigation\n ['arrow-right', 'navigation'],\n ['arrow-left', 'navigation'],\n ['arrow-up', 'navigation'],\n ['arrow-down', 'navigation'],\n ['chevron-right', 'navigation'],\n ['chevron-left', 'navigation'],\n ['chevron-up', 'navigation'],\n ['chevron-down', 'navigation'],\n ['angle-right', 'navigation'],\n ['angle-left', 'navigation'],\n ['angle-up', 'navigation'],\n ['angle-down', 'navigation'],\n ['angles-right', 'navigation'],\n ['angles-left', 'navigation'],\n ['location-dot', 'navigation'],\n ['compass', 'navigation'],\n ['map', 'navigation'],\n ['map-pin', 'navigation'],\n ['route', 'navigation'],\n ['circle-arrow-right', 'navigation'],\n ['circle-arrow-left', 'navigation'],\n ['arrow-trend-up', 'navigation'],\n ['arrow-trend-down', 'navigation'],\n ['right-from-bracket', 'navigation'],\n ['right-to-bracket', 'navigation'],\n // Media\n ['play', 'media'],\n ['pause', 'media'],\n ['stop', 'media'],\n ['forward', 'media'],\n ['backward', 'media'],\n ['forward-step', 'media'],\n ['backward-step', 'media'],\n ['volume-high', 'media'],\n ['volume-low', 'media'],\n ['volume-xmark', 'media'],\n ['volume-off', 'media'],\n ['music', 'media'],\n ['headphones', 'media'],\n ['microphone', 'media'],\n ['microphone-slash', 'media'],\n ['film', 'media'],\n ['camera', 'media'],\n ['camera-rotate', 'media'],\n ['video', 'media'],\n ['image', 'media'],\n ['images', 'media'],\n ['photo-film', 'media'],\n ['podcast', 'media'],\n ['radio', 'media'],\n // Communication\n ['comment', 'communication'],\n ['comments', 'communication'],\n ['comment-dots', 'communication'],\n ['message', 'communication'],\n ['paper-plane', 'communication'],\n ['reply', 'communication'],\n ['reply-all', 'communication'],\n ['at', 'communication'],\n ['hashtag', 'communication'],\n ['wifi', 'communication'],\n ['signal', 'communication'],\n ['rss', 'communication'],\n ['share-nodes', 'communication'],\n ['inbox', 'communication'],\n ['phone-volume', 'communication'],\n ['mobile', 'communication'],\n ['mobile-screen', 'communication'],\n ['laptop', 'communication'],\n ['desktop', 'communication'],\n ['tower-broadcast', 'communication'],\n // Files\n ['file', 'files'],\n ['file-lines', 'files'],\n ['folder', 'files'],\n ['folder-open', 'files'],\n ['folder-plus', 'files'],\n ['folder-minus', 'files'],\n ['file-image', 'files'],\n ['file-pdf', 'files'],\n ['file-code', 'files'],\n ['file-zipper', 'files'],\n ['file-audio', 'files'],\n ['file-video', 'files'],\n ['file-arrow-up', 'files'],\n ['file-arrow-down', 'files'],\n ['database', 'files'],\n ['box', 'files'],\n ['box-open', 'files'],\n ['hard-drive', 'files'],\n ['server', 'files'],\n // People\n ['user', 'people'],\n ['users', 'people'],\n ['user-group', 'people'],\n ['user-plus', 'people'],\n ['user-minus', 'people'],\n ['user-check', 'people'],\n ['user-xmark', 'people'],\n ['user-tie', 'people'],\n ['user-shield', 'people'],\n ['user-secret', 'people'],\n ['person', 'people'],\n ['person-running', 'people'],\n ['person-walking', 'people'],\n ['child', 'people'],\n ['handshake', 'people'],\n ['hand', 'people'],\n ['hands-holding', 'people'],\n ['people-group', 'people'],\n // Objects\n ['pencil', 'objects'],\n ['paintbrush', 'objects'],\n ['eraser', 'objects'],\n ['scissors', 'objects'],\n ['wrench', 'objects'],\n ['screwdriver', 'objects'],\n ['hammer', 'objects'],\n ['toolbox', 'objects'],\n ['graduation-cap', 'objects'],\n ['book', 'objects'],\n ['book-open', 'objects'],\n ['glasses', 'objects'],\n ['microscope', 'objects'],\n ['flask', 'objects'],\n ['stethoscope', 'objects'],\n ['hospital', 'objects'],\n ['building', 'objects'],\n ['city', 'objects'],\n ['car', 'objects'],\n ['truck', 'objects'],\n ['plane', 'objects'],\n ['train', 'objects'],\n ['bicycle', 'objects'],\n ['bus', 'objects'],\n ['rocket', 'objects'],\n ['briefcase', 'objects'],\n ['cart-shopping', 'objects'],\n ['bag-shopping', 'objects'],\n ['credit-card', 'objects'],\n ['money-bill', 'objects'],\n ['chart-bar', 'objects'],\n ['chart-line', 'objects'],\n ['chart-pie', 'objects'],\n ['bolt', 'objects'],\n ['sun', 'objects'],\n ['moon', 'objects'],\n ['snowflake', 'objects'],\n ['fire', 'objects'],\n ['droplet', 'objects'],\n ['leaf', 'objects'],\n ['tree', 'objects'],\n ['earth-americas', 'objects'],\n ['globe', 'objects'],\n ['award', 'objects'],\n ['trophy', 'objects'],\n ['gift', 'objects'],\n ['puzzle-piece', 'objects'],\n];\n\nexport class IconDialog {\n /**\n * @param {import('../Context.js').Context} context\n */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} */\n this._dialog = null;\n this._disposers = [];\n this._savedRange = null;\n this._selectedIcon = null;\n this._activeCat = 'all';\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._ensureFontAwesome();\n // Dialog grid is built lazily on first show() to avoid rendering ~250 icon cells at load time.\n return this;\n }\n\n /**\n * Injects FA 6 Free CSS from CDN if it is not already on the page.\n * This guarantees icon glyphs render in the grid, preview, and in the\n * editor content after insertion — regardless of whether the host page\n * loaded FA itself.\n */\n _ensureFontAwesome() {\n // Already present (icon element or stylesheet link)?\n if (document.getElementById('an-fontawesome-css')) return;\n const links = Array.from(document.querySelectorAll('link[rel=\"stylesheet\"]'))\n .map((l) => l.href || '').join(' ');\n if (/fontawesome|font-awesome/.test(links)) return;\n if (document.querySelector('.fa-solid, .fas, .far, .fab')) return;\n\n const link = document.createElement('link');\n link.id = 'an-fontawesome-css';\n link.rel = 'stylesheet';\n link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css';\n link.crossOrigin = 'anonymous';\n link.referrerPolicy = 'no-referrer';\n document.head.appendChild(link);\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n if (!this._dialog) {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\n withSavedRange((range) => {\n this._savedRange = range;\n });\n this._selectedIcon = null;\n this._activeCat = 'all';\n this._searchInput.value = '';\n // Clear previously selected icon highlight and disable Insert button\n this._grid.querySelectorAll('.an-icon-cell.active').forEach((c) => c.classList.remove('active'));\n this._insertBtn.setAttribute('disabled', '');\n this._updateCatTabs();\n this._filterIcons('', 'all');\n this._updatePreview(null);\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.iconDialog;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.ariaLabel,\n });\n\n const box = createElement('div', { class: 'an-dialog-box an-icon-box' });\n\n // Title row\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '×';\n titleRow.append(title, closeBtn);\n\n // Search\n const searchInput = createElement('input', {\n type: 'search',\n class: 'an-input an-icon-search',\n placeholder: L.searchPlaceholder,\n autocomplete: 'off',\n });\n this._searchInput = searchInput;\n\n // Category tabs\n const catBar = createElement('div', { class: 'an-icon-cats' });\n const allTab = createElement('button', { type: 'button', class: 'an-icon-cat active', 'data-cat': 'all' });\n allTab.textContent = L.all;\n catBar.appendChild(allTab);\n ICON_CATEGORIES.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = (L.categories && L.categories[id]) || label;\n catBar.appendChild(tab);\n });\n this._catBar = catBar;\n\n // Icon grid\n const grid = createElement('div', { class: 'an-icon-grid' });\n ICON_LIST.forEach(([name, cat]) => {\n const cell = createElement('button', { type: 'button', class: 'an-icon-cell', 'data-name': name, 'data-cat': cat, title: name });\n const icon = createElement('i', { class: 'fa-solid fa-' + name, 'aria-hidden': 'true' });\n const label = createElement('span');\n label.textContent = name;\n cell.append(icon, label);\n grid.appendChild(cell);\n });\n this._grid = grid;\n\n // Options row: style + size + color\n const optRow = createElement('div', { class: 'an-icon-options' });\n\n const styleLabel = createElement('label', { class: 'an-label' });\n styleLabel.textContent = L.style;\n const styleSelect = createElement('select', { class: 'an-input an-icon-option-select' });\n [['fa-solid', 'Solid'], ['fa-regular', 'Regular'], ['fa-light', 'Light (Pro)']].forEach(([v, t]) => {\n const opt = createElement('option', { value: v });\n opt.textContent = t;\n styleSelect.appendChild(opt);\n });\n styleSelect.value = 'fa-solid';\n this._styleSelect = styleSelect;\n\n const sizeLabel = createElement('label', { class: 'an-label' });\n sizeLabel.textContent = L.size;\n const sizeSelect = createElement('select', { class: 'an-input an-icon-option-select' });\n [['', 'Inherit'], ['0.75em', '0.75em'], ['1em', '1em'], ['1.25em', '1.25em'], ['1.5em', '1.5em'], ['2em', '2em'], ['3em', '3em']].forEach(([v, t]) => {\n const opt = createElement('option', { value: v });\n if (v === '1em') opt.selected = true;\n opt.textContent = t;\n sizeSelect.appendChild(opt);\n });\n this._sizeSelect = sizeSelect;\n\n const colorLabel = createElement('label', { class: 'an-label' });\n colorLabel.textContent = L.color;\n const colorInput = createElement('input', { type: 'color', class: 'an-icon-color', value: '#000000' });\n this._colorInput = colorInput;\n\n const useColorLabel = createElement('label', { class: 'an-label an-label-inline an-icon-use-color' });\n const useColorCb = createElement('input', { type: 'checkbox', checked: '' });\n this._useColorCb = useColorCb;\n useColorLabel.append(useColorCb, document.createTextNode(L.useColor));\n\n optRow.append(styleLabel, styleSelect, sizeLabel, sizeSelect, colorLabel, colorInput, useColorLabel);\n\n // Preview\n const preview = createElement('div', { class: 'an-icon-preview' });\n const previewHint = createElement('span', { class: 'an-icon-preview-hint' });\n previewHint.textContent = L.selectHint;\n preview.appendChild(previewHint);\n this._preview = preview;\n\n // Actions\n const btnRow = createElement('div', { class: 'an-dialog-actions' });\n const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary', disabled: '' });\n insertBtn.textContent = L.insertBtn;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = L.cancelBtn;\n btnRow.append(insertBtn, cancelBtn);\n this._insertBtn = insertBtn;\n\n box.append(titleRow, searchInput, catBar, grid, optRow, preview, btnRow);\n overlay.appendChild(box);\n\n // -------------------------------------------------------------------------\n // Events\n // -------------------------------------------------------------------------\n\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(cancelBtn, 'click', () => this._close());\n const d3 = on(insertBtn, 'click', () => this._onInsert());\n const d4 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d5 = on(searchInput, 'input', () => this._filterIcons(searchInput.value, this._activeCat));\n const d6 = on(catBar, 'click', (e) => {\n const tab = e.target.closest('[data-cat]');\n if (tab) {\n this._activeCat = tab.dataset.cat;\n this._updateCatTabs();\n this._filterIcons(this._searchInput.value, this._activeCat);\n }\n });\n const d7 = on(grid, 'click', (e) => {\n const cell = e.target.closest('.an-icon-cell');\n if (cell) this._selectIcon(cell.dataset.name);\n });\n const d8 = on(styleSelect, 'change', () => this._updatePreview(this._selectedIcon));\n const d9 = on(sizeSelect, 'change', () => this._updatePreview(this._selectedIcon));\n const d10 = on(colorInput, 'input', () => this._updatePreview(this._selectedIcon));\n const d11 = on(useColorCb, 'change', () => this._updatePreview(this._selectedIcon));\n\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Filter / select\n // ---------------------------------------------------------------------------\n\n _updateCatTabs() {\n this._catBar.querySelectorAll('.an-icon-cat').forEach((tab) => {\n tab.classList.toggle('active', tab.dataset.cat === this._activeCat);\n });\n }\n\n _filterIcons(query, cat) {\n const q = (query || '').trim().toLowerCase();\n let visibleCount = 0;\n this._grid.querySelectorAll('.an-icon-cell').forEach((cell) => {\n const name = cell.dataset.name;\n const cellCat = cell.dataset.cat;\n const matchesCat = !cat || cat === 'all' || cellCat === cat;\n const matchesQuery = !q || name.includes(q);\n const visible = matchesCat && matchesQuery;\n cell.style.display = visible ? '' : 'none';\n if (visible) visibleCount++;\n });\n // Show empty state if needed\n let empty = this._grid.querySelector('.an-icon-empty');\n if (!empty) {\n empty = createElement('div', { class: 'an-icon-empty' });\n empty.textContent = 'No icons found';\n this._grid.appendChild(empty);\n }\n empty.style.display = visibleCount > 0 ? 'none' : '';\n }\n\n _selectIcon(name) {\n this._selectedIcon = name;\n // Highlight selected cell\n this._grid.querySelectorAll('.an-icon-cell').forEach((cell) => {\n cell.classList.toggle('active', cell.dataset.name === name);\n });\n // Enable insert button\n this._insertBtn.removeAttribute('disabled');\n // Update preview\n this._updatePreview(name);\n }\n\n _updatePreview(name) {\n if (!this._preview) return;\n if (!name) {\n this._preview.innerHTML = '<span class=\"an-icon-preview-hint\">Select an icon</span>';\n return;\n }\n const cls = (this._styleSelect && this._styleSelect.value) || 'fa-solid';\n const size = (this._sizeSelect && this._sizeSelect.value) || '1em';\n const useColor = this._useColorCb ? this._useColorCb.checked : false;\n const color = (useColor && this._colorInput) ? this._colorInput.value : '';\n const styleAttr = [\n size ? `font-size:${size}` : '',\n color ? `color:${color}` : '',\n ].filter(Boolean).join(';');\n // Use innerHTML — atomic, no partial-update risk\n this._preview.innerHTML =\n `<i class=\"${cls} fa-${name}\" aria-hidden=\"true\"${\n styleAttr ? ` style=\"${styleAttr}\"` : ''\n }></i>` +\n `<div class=\"an-icon-preview-name\">${cls} fa-${name}</div>`;\n }\n\n // ---------------------------------------------------------------------------\n // Insert\n // ---------------------------------------------------------------------------\n\n _onInsert() {\n if (!this._selectedIcon) return;\n\n const cls = (this._styleSelect && this._styleSelect.value) || 'fa-solid';\n const size = (this._sizeSelect && this._sizeSelect.value) || '';\n const useColor = this._useColorCb ? this._useColorCb.checked : false;\n const color = (useColor && this._colorInput) ? this._colorInput.value : '';\n const styleParts = [\n size ? `font-size:${size}` : '',\n color ? `color:${color}` : '',\n ].filter(Boolean);\n\n const iconEl = document.createElement('i');\n iconEl.className = `${cls} fa-${this._selectedIcon}`;\n iconEl.setAttribute('aria-hidden', 'true');\n iconEl.setAttribute('contenteditable', 'false');\n if (styleParts.length) iconEl.setAttribute('style', styleParts.join(';'));\n\n const savedRange = this._savedRange;\n const editable = this.context.layoutInfo.editable;\n\n // ---- Same ordering as ImageDialog (the proven pattern) ----\n // 1. Restore the selection while the dialog is still mounted\n if (savedRange) savedRange.select();\n\n // 2. Get the now-live range from the selection\n const sel = window.getSelection();\n let range = sel && sel.rangeCount > 0 ? sel.getRangeAt(0) : null;\n if (!range) {\n range = document.createRange();\n range.selectNodeContents(editable);\n range.collapse(false);\n }\n\n // 3. Insert the <i> node directly — never via execCommand/insertHTML\n // (execCommand leaves the caret inside the inserted element)\n //\n // E-1: When the range covers the entire content of a <td>/<th>,\n // deleteContents() can drift the range endpoint outside the cell in some\n // browsers. Save the cell reference first and re-anchor after deletion.\n const _sc = range.startContainer;\n const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest?.('td, th');\n range.deleteContents();\n if (_tdAnchor && _tdAnchor.isConnected && !_tdAnchor.contains(range.startContainer)) {\n range.setStart(_tdAnchor, 0);\n range.collapse(true);\n }\n range.insertNode(iconEl);\n\n // 4. Place cursor after the icon.\n // Keep a text anchor (\\u200B) after the icon so ArrowLeft/ArrowRight and\n // caret placement at end-of-line stay stable across browsers.\n let caretTextNode = iconEl.nextSibling;\n if (!caretTextNode || caretTextNode.nodeType !== Node.TEXT_NODE) {\n caretTextNode = document.createTextNode('\\u200B');\n iconEl.parentNode.insertBefore(caretTextNode, iconEl.nextSibling);\n } else if (!caretTextNode.textContent) {\n // Split text-node insertions can leave an empty text node after icon.\n // Fill it with ZWS so caret-after-icon remains stable at end-of-line.\n caretTextNode.textContent = '\\u200B';\n }\n\n const caretOffset = ((caretTextNode.textContent || '').startsWith('\\u200B')) ? 1 : 0;\n const caretRange = document.createRange();\n caretRange.setStart(caretTextNode, Math.min(caretOffset, caretTextNode.textContent.length));\n caretRange.collapse(true);\n if (sel) {\n sel.removeAllRanges();\n sel.addRange(caretRange);\n }\n\n // 5. Close dialog last — same as ImageDialog\n this._close();\n\n // 6. Restore editor focus (needed for toolbar refresh via afterCommand)\n editable.focus();\n if (sel) {\n // Some browsers reset selection when refocusing editable after closing dialog.\n sel.removeAllRanges();\n sel.addRange(caretRange);\n }\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Open / Close\n // ---------------------------------------------------------------------------\n\n _open() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._searchInput && this._searchInput.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._savedRange = null;\n this._selectedIcon = null;\n }\n}\n","// ContextMenu.js - Right-click context menu for editor actions\nimport { createElement, on } from '../core/dom.js';\nimport { sanitiseHTML } from '../core/sanitise.js';\n\n// SVG icon map — 16×16 Heroicons-style paths\nconst ICONS = {\n undo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/></svg>`,\n redo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/></svg>`,\n cut: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"6\" cy=\"20\" r=\"3\"/><circle cx=\"6\" cy=\"4\" r=\"3\"/><line x1=\"19\" y1=\"5\" x2=\"6\" y2=\"19\"/><line x1=\"19\" y1=\"19\" x2=\"13.5\" y2=\"13.5\"/></svg>`,\n copy: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`,\n paste: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\"/></svg>`,\n bold: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/></svg>`,\n italic: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/></svg>`,\n underline: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/></svg>`,\n link: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`,\n image: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/></svg>`,\n video: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"23 7 16 12 23 17 23 7\"/><rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\"/></svg>`,\n // Image format operations\n floatLeft: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"12\" y1=\"6\" x2=\"22\" y2=\"6\"/><line x1=\"12\" y1=\"9\" x2=\"22\" y2=\"9\"/><line x1=\"12\" y1=\"12\" x2=\"22\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatRight: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"14\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"2\" y1=\"6\" x2=\"12\" y2=\"6\"/><line x1=\"2\" y1=\"9\" x2=\"12\" y2=\"9\"/><line x1=\"2\" y1=\"12\" x2=\"12\" y2=\"12\"/><line x1=\"2\" y1=\"16\" x2=\"22\" y2=\"16\"/><line x1=\"2\" y1=\"20\" x2=\"18\" y2=\"20\"/></svg>`,\n floatNone: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"8\" height=\"8\" rx=\"1\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"3\" y1=\"19\" x2=\"17\" y2=\"19\"/></svg>`,\n originalSize:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/></svg>`,\n deleteImg: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n // Video format operations\n videoAlign: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polygon points=\"23 7 16 12 23 17 23 7\"/><rect x=\"1\" y=\"5\" width=\"15\" height=\"14\" rx=\"2\"/></svg>`,\n deleteVideo: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\"/></svg>`,\n // Format painter operations\n copyFormat: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`,\n pasteFormat: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\"/><path d=\"m9 14 2 2 4-4\"/></svg>`,\n removeFormat:`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/></svg>`,\n // Table\n table: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"1\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>`,\n // Color\n textColor: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/></svg>`,\n highlightColor: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\"/></svg>`,\n noColor: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\"/><line x1=\"20\" y1=\"4\" x2=\"4\" y2=\"20\"/></svg>`,\n back: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 18 9 12 15 6\"/></svg>`,\n};\n\nconst COLOR_PRESETS = [\n // Grayscale\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n // Saturated\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n // Pastel\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\n];\n\nfunction makeColorSubItems(colorType) {\n const label = colorType === 'foreColor' ? 'Text Color' : 'Highlight Color';\n const localeKey = colorType === 'foreColor' ? 'textColor' : 'highlightColor';\n return () => [\n { back: true, label, localeKey, navigate: () => defaultItems },\n { colorPalette: true, colorType },\n ];\n}\n\nconst defaultItems = [\n { name: 'cut', label: 'Cut', icon: ICONS.cut, action: () => document.execCommand('cut') },\n { name: 'copy', label: 'Copy', icon: ICONS.copy, action: () => document.execCommand('copy') },\n { name: 'paste', label: 'Paste', icon: ICONS.paste, action: (ctx) => {\n if (!navigator.clipboard) return;\n const editable = ctx.layoutInfo && ctx.layoutInfo.editable;\n if (!editable) return;\n // Prefer read() to get rich HTML; fall back to readText() for plain text\n const doInsert = (html, text) => {\n editable.focus();\n if (html) {\n const clean = sanitiseHTML(html);\n document.execCommand('insertHTML', false, clean);\n } else if (text) {\n document.execCommand('insertText', false, text);\n }\n ctx.invoke('editor.afterCommand');\n };\n if (typeof navigator.clipboard.read === 'function') {\n navigator.clipboard.read().then((items) => {\n for (const item of items) {\n if (item.types.includes('text/html')) {\n item.getType('text/html').then((blob) => blob.text()).then((html) => doInsert(html, null));\n return;\n }\n }\n // No HTML item — fall through to plain text\n navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});\n }).catch(() => {\n // read() denied → try readText() as fallback\n navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});\n });\n } else if (typeof navigator.clipboard.readText === 'function') {\n navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});\n }\n } },\n { separator: true },\n { name: 'bold', label: 'Bold', icon: ICONS.bold, action: (ctx) => ctx.invoke('editor.bold') },\n { name: 'italic', label: 'Italic', icon: ICONS.italic, action: (ctx) => ctx.invoke('editor.italic') },\n { name: 'underline', label: 'Underline', icon: ICONS.underline, action: (ctx) => ctx.invoke('editor.underline') },\n { separator: true },\n { name: 'textColor', label: 'Text Color', icon: ICONS.textColor, colorStrip: 'foreColor', navigate: makeColorSubItems('foreColor') },\n { name: 'highlightColor', label: 'Highlight Color', icon: ICONS.highlightColor, colorStrip: 'hiliteColor', navigate: makeColorSubItems('hiliteColor') },\n { separator: true },\n { name: 'copyFormat', label: 'Copy Format', icon: ICONS.copyFormat, action: (ctx) => ctx.invoke('contextMenu.copyFormat') },\n { name: 'pasteFormat', label: 'Paste Format', icon: ICONS.pasteFormat, action: (ctx) => ctx.invoke('contextMenu.pasteFormat'), disabled: (ctx) => !ctx.invoke('contextMenu.hasCopiedFormat') },\n { name: 'removeFormat', label: 'Remove Format', icon: ICONS.removeFormat, action: (ctx) => ctx.invoke('contextMenu.removeFormat') },\n { separator: true },\n { name: 'link', label: 'Insert Link', icon: ICONS.link, action: (ctx) => ctx.invoke('linkDialog.show') },\n { name: 'image', label: 'Insert Image', icon: ICONS.image, action: (ctx) => ctx.invoke('imageDialog.show') },\n { name: 'video', label: 'Insert Video', icon: ICONS.video, action: (ctx) => ctx.invoke('videoDialog.show') },\n { name: 'table', label: 'Insert Table', icon: ICONS.table, tableGrid: true },\n];\n\nexport class ContextMenu {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options || {};\n this._items = (this.options.contextMenu && this.options.contextMenu.items) || defaultItems;\n this.el = null;\n this._disposers = [];\n this._menuDisposers = []; // disposers for dynamically-rendered menu buttons\n this._lastX = 0;\n this._lastY = 0;\n this._copiedFormat = null;\n this._savedRange = null;\n }\n\n initialize() {\n this.el = createElement('div', { class: 'an-contextmenu', role: 'menu', 'aria-hidden': 'true' });\n this.el.style.display = 'none';\n document.body.appendChild(this.el);\n\n this._renderItems(this._items);\n\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (editable) {\n this._disposers.push(on(editable, 'contextmenu', (e) => this._onContextMenu(e)));\n }\n\n this._disposers.push(on(document, 'click', (e) => this._maybeHide(e)));\n this._disposers.push(on(document, 'keydown', (e) => { if (e.key === 'Escape') this.hide(); }));\n this._disposers.push(on(window, 'scroll', () => this.hide(), { passive: true }));\n\n return this;\n }\n\n destroy() {\n this._menuDisposers.forEach((d) => { try { d(); } catch (e) {} });\n this._menuDisposers = [];\n this._disposers.forEach((d) => { try { d(); } catch (e) {} });\n this._disposers = [];\n if (this.el && this.el.parentNode) this.el.parentNode.removeChild(this.el);\n this.el = null;\n }\n\n _renderItems(items) {\n // Clean up previously registered per-item listeners\n this._menuDisposers.forEach((d) => d());\n this._menuDisposers = [];\n\n if (!this.el) return;\n this.el.innerHTML = '';\n\n items.forEach((it) => {\n if (it.separator || it.sep) {\n this.el.appendChild(createElement('div', { class: 'an-context-sep' }));\n return;\n }\n\n // Back-navigation header\n if (it.back) {\n const backBtn = createElement('button', { type: 'button', class: 'an-context-back' });\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = ICONS.back;\n backBtn.appendChild(iconSpan);\n const backLabel = (it.localeKey && this.context.locale.contextMenu[it.localeKey]) || it.label || this.context.locale.contextMenu.back || 'Back';\n backBtn.appendChild(createElement('span', { class: 'an-context-label' }, [backLabel]));\n const off = on(backBtn, 'click', (e) => {\n e.stopPropagation();\n const curLeft = parseFloat(this.el.style.left);\n const curTop = parseFloat(this.el.style.top);\n this._renderItems(it.navigate());\n this._reposition(curLeft, curTop);\n });\n this._menuDisposers.push(off);\n this.el.appendChild(backBtn);\n return;\n }\n\n // Submenu-navigate item (shows ▶ chevron, re-renders without closing)\n if (it.navigate) {\n const btn = createElement('button', { type: 'button', class: 'an-context-item an-context-submenu', 'data-name': it.name || '' });\n if (it.icon) {\n if (it.colorStrip) {\n // Toolbar-style icon: SVG stacked above a colored strip\n const iconWrap = createElement('span', { class: 'an-context-icon an-context-icon--color', 'aria-hidden': 'true' });\n const svgSpan = createElement('span', { class: 'an-context-icon-svg' });\n svgSpan.innerHTML = it.icon;\n const strip = createElement('span', { class: 'an-context-color-strip' });\n strip.style.background = this._getSelectionColor(it.colorStrip);\n iconWrap.appendChild(svgSpan);\n iconWrap.appendChild(strip);\n btn.appendChild(iconWrap);\n } else {\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = it.icon;\n btn.appendChild(iconSpan);\n }\n }\n btn.appendChild(createElement('span', { class: 'an-context-label' }, [(this.context.locale.contextMenu[it.name] || it.label || it.name)]));\n const chevron = createElement('span', { class: 'an-context-chevron', 'aria-hidden': 'true' });\n chevron.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 18 15 12 9 6\"/></svg>`;\n btn.appendChild(chevron);\n const off = on(btn, 'click', (e) => {\n e.stopPropagation();\n const curLeft = parseFloat(this.el.style.left);\n const curTop = parseFloat(this.el.style.top);\n this._renderItems(it.navigate());\n this._reposition(curLeft, curTop);\n });\n this._menuDisposers.push(off);\n this.el.appendChild(btn);\n return;\n }\n\n // Color palette item — renders inline color swatches\n if (it.colorPalette) {\n const palette = createElement('div', { class: 'an-context-color-palette' });\n COLOR_PRESETS.forEach((color) => {\n const sw = createElement('div', {\n class: 'an-context-color-swatch',\n title: color,\n role: 'button',\n 'aria-label': color,\n });\n sw.style.background = color;\n const offSw = on(sw, 'click', (e) => { e.stopPropagation(); this._applyColor(it.colorType, color); });\n this._menuDisposers.push(offSw);\n palette.appendChild(sw);\n });\n if (it.colorType === 'hiliteColor') {\n const noColor = createElement('div', {\n class: 'an-context-color-swatch an-context-color-none',\n title: this.context.locale.contextMenu.noHighlight || 'No highlight',\n role: 'button',\n 'aria-label': this.context.locale.contextMenu.noHighlight || 'No highlight',\n });\n noColor.innerHTML = ICONS.noColor;\n const offNo = on(noColor, 'click', (e) => { e.stopPropagation(); this._applyColor('hiliteColor', 'transparent'); });\n this._menuDisposers.push(offNo);\n palette.appendChild(noColor);\n }\n this.el.appendChild(palette);\n\n // Custom color row\n const customRow = createElement('div', { class: 'an-context-color-custom' });\n const colorInput = createElement('input', {\n type: 'color',\n value: it.colorType === 'foreColor' ? '#000000' : '#ffff00',\n title: this.context.locale.contextMenu.customColor || 'Custom color',\n 'aria-label': this.context.locale.contextMenu.customColor || 'Custom color',\n });\n const customLabel = createElement('span', {}, [this.context.locale.contextMenu.customColorLabel || 'Custom…']);\n const offCustom = on(colorInput, 'change', () => this._applyColor(it.colorType, colorInput.value));\n this._menuDisposers.push(offCustom);\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n this.el.appendChild(customRow);\n return;\n }\n\n // Table grid picker item — expands an inline grid panel when clicked\n if (it.tableGrid) {\n const GRID_ROWS = 8, GRID_COLS = 8;\n const wrapper = createElement('div', { class: 'an-context-table-wrap' });\n\n const headerBtn = createElement('button', { type: 'button', class: 'an-context-item an-context-submenu', 'data-name': it.name || 'table' });\n if (it.icon) {\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = it.icon;\n headerBtn.appendChild(iconSpan);\n }\n headerBtn.appendChild(createElement('span', { class: 'an-context-label' }, [this.context.locale.contextMenu.table || it.label || 'Insert Table']));\n const chevron = createElement('span', { class: 'an-context-chevron', 'aria-hidden': 'true' });\n chevron.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 18 15 12 9 6\"/></svg>`;\n headerBtn.appendChild(chevron);\n\n const panel = createElement('div', { class: 'an-context-table-grid-panel' });\n panel.style.display = 'none';\n\n const gridEl = createElement('div', { class: 'an-table-grid' });\n gridEl.style.gridTemplateColumns = `repeat(${GRID_COLS}, 16px)`;\n const labelEl = createElement('div', { class: 'an-table-label' });\n labelEl.textContent = 'Insert Table';\n\n const cells = [];\n for (let r = 1; r <= GRID_ROWS; r++) {\n for (let c = 1; c <= GRID_COLS; c++) {\n const cell = createElement('div', { class: 'an-table-cell', 'data-row': String(r), 'data-col': String(c) });\n cell.style.width = '16px';\n cell.style.height = '16px';\n cells.push(cell);\n gridEl.appendChild(cell);\n }\n }\n\n const setHighlight = (rows, cols) => {\n cells.forEach((cell) => {\n cell.classList.toggle('active', +cell.dataset.row <= rows && +cell.dataset.col <= cols);\n });\n labelEl.textContent = (rows && cols) ? `${cols} × ${rows}` : (this.context.locale.contextMenu.table || 'Insert Table');\n };\n\n panel.appendChild(gridEl);\n panel.appendChild(labelEl);\n\n let expanded = false;\n const offHeader = on(headerBtn, 'click', (e) => {\n e.stopPropagation();\n expanded = !expanded;\n panel.style.display = expanded ? '' : 'none';\n chevron.style.transform = expanded ? 'rotate(90deg)' : '';\n this._reposition();\n });\n this._menuDisposers.push(offHeader);\n\n const offMove = on(gridEl, 'mousemove', (e) => {\n const cell = e.target.closest('[data-row]');\n if (!cell) return;\n setHighlight(+cell.dataset.row, +cell.dataset.col);\n });\n const offLeave = on(gridEl, 'mouseleave', () => setHighlight(0, 0));\n const offClick = on(gridEl, 'click', (e) => {\n const cell = e.target.closest('[data-row]');\n if (!cell) return;\n const rows = +cell.dataset.row;\n const cols = +cell.dataset.col;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (editable && this._savedRange) {\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n }\n this.hide();\n this.context.invoke('editor.insertTable', cols, rows);\n });\n this._menuDisposers.push(offMove, offLeave, offClick);\n\n wrapper.appendChild(headerBtn);\n wrapper.appendChild(panel);\n this.el.appendChild(wrapper);\n return;\n }\n\n // Regular item\n const btn = createElement('button', { type: 'button', class: 'an-context-item', 'data-name': it.name || '' });\n if (typeof it.disabled === 'function' ? it.disabled(this.context) : !!it.disabled) btn.disabled = true;\n if (it.icon) {\n const iconSpan = createElement('span', { class: 'an-context-icon', 'aria-hidden': 'true' });\n iconSpan.innerHTML = it.icon;\n btn.appendChild(iconSpan);\n }\n btn.appendChild(createElement('span', { class: 'an-context-label' }, [(this.context.locale.contextMenu[it.name] || it.label || it.name)]));\n const off = on(btn, 'click', (e) => {\n e.stopPropagation();\n this.hide();\n try { it.action(this.context); } catch (err) { console.error(err); }\n });\n this._menuDisposers.push(off);\n this.el.appendChild(btn);\n });\n }\n\n _onContextMenu(event) {\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable) return;\n if (!editable.contains(event.target)) return;\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n event.preventDefault();\n\n const winSel = window.getSelection();\n this._savedRange = (winSel && winSel.rangeCount > 0) ? winSel.getRangeAt(0).cloneRange() : null;\n this._renderItems(this._items);\n\n // Open below the selected text so the selection stays visible.\n // Only apply when there is a real (non-collapsed) selection — a collapsed range\n // (cursor only) also has height > 0, which would misplace the menu relative\n // to the actual click point.\n let openX = event.clientX;\n let openY = event.clientY;\n if (this._savedRange && !this._savedRange.collapsed) {\n try {\n const selRect = this._savedRange.getBoundingClientRect();\n if (selRect.width > 0 && selRect.height > 0) {\n // Keep X at click position (feels natural); Y just below the selection.\n openY = selRect.bottom + 4;\n }\n } catch (_) {}\n }\n\n this._lastX = openX;\n this._lastY = openY;\n this.showAt(openX, openY);\n }\n\n _maybeHide(event) {\n if (!this.el) return;\n if (!this.el.contains(event.target)) this.hide();\n }\n\n showAt(x, y) {\n if (!this.el) return;\n this.el.style.display = 'block';\n this._reposition(x, y);\n this.el.setAttribute('aria-hidden', 'false');\n this.context.triggerEvent('contextMenu:show');\n }\n\n _reposition(x, y) {\n if (!this.el) return;\n const rx = x !== undefined ? x : this._lastX;\n const ry = y !== undefined ? y : this._lastY;\n const w = this.el.offsetWidth;\n const h = this.el.offsetHeight;\n let left = rx;\n let top = ry;\n // Clamp to viewport so the menu never overflows the screen edge\n if (left + w > window.innerWidth - 8) left = window.innerWidth - w - 8;\n if (left < 8) left = 8;\n if (top + h > window.innerHeight - 8) top = window.innerHeight - h - 8;\n if (top < 8) top = 8;\n this.el.style.left = `${left}px`;\n this.el.style.top = `${top}px`;\n }\n\n hide() {\n if (!this.el) return;\n this.el.style.display = 'none';\n this.el.setAttribute('aria-hidden', 'true');\n this.context.triggerEvent('contextMenu:hide');\n }\n\n // ---------------------------------------------------------------------------\n // Format operations (Copy Format / Paste Format / Remove Format)\n // ---------------------------------------------------------------------------\n\n /** Read the current selection's text or highlight color for the strip.\n * @param {'foreColor'|'hiliteColor'} type\n * @returns {string} CSS color string\n */\n _getSelectionColor(type) {\n const range = this._savedRange;\n if (!range) return type === 'foreColor' ? '#000000' : 'transparent';\n let node = range.startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node) return type === 'foreColor' ? '#000000' : 'transparent';\n const cs = window.getComputedStyle(node);\n if (type === 'foreColor') {\n return cs.color || '#000000';\n }\n const bg = cs.backgroundColor;\n return (!bg || bg === 'rgba(0, 0, 0, 0)' || bg === 'transparent') ? 'transparent' : bg;\n }\n\n /** Restore selection, apply a color command, then hide the menu. */\n _applyColor(type, color) {\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable || !this._savedRange) return;\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n document.execCommand(type, false, color);\n this.context.invoke('editor.afterCommand');\n this.hide();\n }\n\n /** Returns true if a format has been copied — used to disable Paste Format. */\n hasCopiedFormat() { return !!this._copiedFormat; }\n\n /** Snapshot inline styles at the selection anchor node. */\n copyFormat() {\n const range = this._savedRange;\n if (!range) return;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n let node = range.startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || !editable || !editable.contains(node)) return;\n\n // Walk up to collect explicitly-set inline properties from the nearest styled ancestor\n const cs = window.getComputedStyle(node);\n\n // Detect if an explicit font-family / font-size is set on an element (not just inherited)\n const explicitFontFamily = this._findExplicitStyle(node, editable, 'fontFamily');\n const explicitFontSize = this._findExplicitStyle(node, editable, 'fontSize');\n\n this._copiedFormat = {\n bold: parseInt(cs.fontWeight, 10) >= 700,\n italic: cs.fontStyle === 'italic' || cs.fontStyle === 'oblique',\n underline: (cs.textDecorationLine || '').includes('underline'),\n strikethrough: (cs.textDecorationLine || '').includes('line-through'),\n fontFamily: explicitFontFamily,\n fontSize: explicitFontSize,\n color: this._isDefaultColor(cs.color) ? null : cs.color,\n backgroundColor: cs.backgroundColor,\n };\n }\n\n /** Walk up the tree looking for a property explicitly set in inline style. Returns null if only inherited. */\n _findExplicitStyle(node, boundary, prop) {\n let el = node;\n while (el && el !== boundary && el !== document.body) {\n if (el.style && el.style[prop]) return el.style[prop];\n // also check font element attributes\n if (el.nodeName === 'FONT') {\n if (prop === 'fontFamily' && el.getAttribute('face')) return el.getAttribute('face');\n if (prop === 'fontSize' && el.getAttribute('size')) {\n // font size attribute is 1-7; skip these since we need px\n return null;\n }\n }\n el = el.parentElement;\n }\n return null;\n }\n\n /** Checks if a computed color looks like the default browser text color (black). */\n _isDefaultColor(color) {\n return !color || color === 'rgb(0, 0, 0)' || color === 'rgba(0, 0, 0, 0)' || color === 'transparent';\n }\n\n /** Apply the most-recently copied format to the saved selection. */\n pasteFormat() {\n if (!this._copiedFormat || !this._savedRange) return;\n const fmt = this._copiedFormat;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable) return;\n\n // CRITICAL: focus the editable FIRST, then restore selection.\n // Calling focus() after addRange() can wipe the selection in Chrome/Firefox.\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n\n // Strip existing inline formatting so we start from a clean state.\n // After removeFormat, bold/italic/underline/strikethrough are guaranteed off.\n document.execCommand('removeFormat');\n\n // Apply each format positively — no toggle-check needed after removeFormat.\n if (fmt.bold) document.execCommand('bold');\n if (fmt.italic) document.execCommand('italic');\n if (fmt.underline) document.execCommand('underline');\n if (fmt.strikethrough) document.execCommand('strikeThrough');\n\n if (fmt.color) document.execCommand('foreColor', false, fmt.color);\n\n const isTransparent = (c) => !c || c === 'rgba(0, 0, 0, 0)' || c === 'transparent';\n if (!isTransparent(fmt.backgroundColor)) {\n document.execCommand('hiliteColor', false, fmt.backgroundColor);\n }\n\n // Font family — apply BEFORE font-size DOM manipulation so the selection is still intact.\n if (fmt.fontFamily) {\n document.execCommand('fontName', false, fmt.fontFamily);\n }\n\n // Font size — use a unique data-marker to avoid touching pre-existing font[size=\"7\"] nodes.\n if (fmt.fontSize) {\n const marker = `fs-${Date.now()}`;\n // Snapshot pre-existing font[size=\"7\"] BEFORE execCommand so we don't accidentally\n // replace nodes that were already in the document (the comment below was aspirational\n // but the original code never actually excluded them — this Set approach is the fix).\n const preExisting = new Set(editable.querySelectorAll('font[size=\"7\"]'));\n document.execCommand('fontSize', false, '7');\n // Mark only the NEWLY created font[size=\"7\"] elements.\n editable.querySelectorAll('font[size=\"7\"]').forEach((el) => {\n if (!preExisting.has(el)) el.setAttribute('data-an-tmp', marker);\n });\n editable.querySelectorAll(`[data-an-tmp=\"${marker}\"]`).forEach((el) => {\n const span = document.createElement('span');\n span.style.fontSize = fmt.fontSize;\n el.parentNode.insertBefore(span, el);\n while (el.firstChild) span.appendChild(el.firstChild);\n el.parentNode.removeChild(el);\n });\n }\n\n this.context.invoke('editor.afterCommand');\n }\n\n /** Strip all inline formatting from the saved selection. */\n removeFormat() {\n if (!this._savedRange) return;\n const editable = this.context.layoutInfo && this.context.layoutInfo.editable;\n if (!editable) return;\n\n editable.focus();\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange.cloneRange());\n\n document.execCommand('removeFormat');\n\n const range = sel.getRangeAt(0);\n const root = range.commonAncestorContainer;\n const rootEl = root.nodeType === Node.TEXT_NODE ? root.parentElement : root;\n const iter = document.createNodeIterator(rootEl, NodeFilter.SHOW_ELEMENT);\n let el;\n while ((el = iter.nextNode())) {\n if (!editable.contains(el) || el === editable) continue;\n try { if (range.intersectsNode(el)) el.removeAttribute('style'); } catch { /* ignore */ }\n }\n\n this.context.invoke('editor.afterCommand');\n }\n}\n\nexport default ContextMenu;\n","/**\n * ShortcutsDialog.js - Modal dialog listing all keyboard shortcuts.\n * Opened via the toolbar '?' button or Shift+? inside the editor.\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\n\nconst SHORTCUTS = [\n {\n category: 'Text Formatting',\n items: [\n { keys: 'Ctrl + B', action: 'Bold' },\n { keys: 'Ctrl + I', action: 'Italic' },\n { keys: 'Ctrl + U', action: 'Underline' },\n { keys: 'Ctrl + K', action: 'Insert / edit link' },\n ],\n },\n {\n category: 'History',\n items: [\n { keys: 'Ctrl + Z', action: 'Undo' },\n { keys: 'Ctrl + Y / Ctrl + Shift + Z', action: 'Redo' },\n ],\n },\n {\n category: 'Selection & Navigation',\n items: [\n { keys: 'Ctrl + A', action: 'Select all content' },\n { keys: 'Tab', action: 'Indent list item / insert spaces' },\n { keys: 'Shift + Tab', action: 'Outdent list item' },\n ],\n },\n {\n category: 'Clipboard',\n items: [\n { keys: 'Ctrl + Shift + V', action: 'Paste as plain text' },\n ],\n },\n {\n category: 'Find & Replace',\n items: [\n { keys: 'Ctrl + F', action: 'Find in document' },\n { keys: 'Ctrl + H', action: 'Find & Replace' },\n ],\n },\n {\n category: 'Editor',\n items: [\n { keys: 'Ctrl + Shift + /', action: 'Show this keyboard shortcuts dialog' },\n ],\n },\n];\n\nexport class ShortcutsDialog {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this._dialog = null;\n this._closeBtn = null;\n this._disposers = [];\n }\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n show() {\n if (this._dialog) {\n this._dialog.style.display = 'flex';\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n setTimeout(() => this._closeBtn && this._closeBtn.focus(), 50);\n }\n }\n\n _close() {\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n }\n\n _buildDialog() {\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': this.context.locale.shortcutsDialog.ariaLabel,\n });\n\n const box = createElement('div', { class: 'an-dialog-box an-shortcuts-box' });\n\n // Title row with close button\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = this.context.locale.shortcutsDialog.title;\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n 'aria-label': this.context.locale.shortcutsDialog.close,\n });\n closeBtn.textContent = '×';\n this._closeBtn = closeBtn;\n titleRow.append(title, closeBtn);\n box.appendChild(titleRow);\n\n const shortcuts = this.context.locale.shortcutsDialog.shortcuts || SHORTCUTS;\n shortcuts.forEach(({ category, items }) => {\n const catEl = createElement('div', { class: 'an-shortcuts-cat' });\n catEl.textContent = category;\n box.appendChild(catEl);\n\n const table = createElement('div', { class: 'an-shortcuts-table' });\n items.forEach(({ keys, action }) => {\n const row = createElement('div', { class: 'an-shortcuts-row' });\n const keyEl = createElement('span', { class: 'an-shortcuts-key' });\n keyEl.textContent = keys;\n const actEl = createElement('span', { class: 'an-shortcuts-action' });\n actEl.textContent = action;\n row.append(keyEl, actEl);\n table.appendChild(row);\n });\n box.appendChild(table);\n });\n\n overlay.appendChild(box);\n\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n this._disposers.push(d1, d2);\n\n return overlay;\n }\n}\n","/**\n * FindReplace.js - Find & Replace dialog\n *\n * Opens via Ctrl+F (find only) or Ctrl+H (find + replace).\n * Uses TreeWalker to locate text matches and wraps them with <mark> elements\n * for highlighting. Supports case-sensitive search, Prev/Next navigation and\n * single / replace-all replacement.\n */\n\nimport { createElement, on, trapFocus } from '../core/dom.js';\n\nexport class FindReplace {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n\n /** @type {HTMLElement|null} */\n this._dialog = null;\n /** @type {HTMLInputElement|null} */\n this._findInput = null;\n /** @type {HTMLInputElement|null} */\n this._replaceInput = null;\n /** @type {HTMLInputElement|null} */\n this._caseCheckbox = null;\n /** @type {HTMLElement|null} */\n this._counterEl = null;\n /** @type {HTMLElement|null} */\n this._closeBtn = null;\n\n /** Live matches — each entry is { mark: HTMLElement } after highlighting */\n this._matches = [];\n this._currentIndex = -1;\n this._caseSensitive = false;\n /** @type {'find'|'replace'} */\n this._mode = 'find';\n\n /** Cached compiled regex — reused when query and case-sensitivity are unchanged */\n this._queryRegex = null;\n this._lastQuery = null;\n this._lastCaseSensitive = null;\n\n this._disposers = [];\n this._removeTrap = null;\n this._focusTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n return this;\n }\n\n destroy() {\n clearTimeout(this._focusTimer);\n this._focusTimer = null;\n this._clearHighlights();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this._dialog && this._dialog.parentNode) {\n this._dialog.parentNode.removeChild(this._dialog);\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the dialog in 'find' or 'replace' mode.\n * @param {'find'|'replace'} [mode='find']\n */\n show(mode = 'find') {\n this._mode = mode;\n this._updateMode();\n this._open();\n // Pre-select whatever was previously typed so the user can retype immediately\n clearTimeout(this._focusTimer);\n this._focusTimer = setTimeout(() => {\n if (this._findInput) {\n this._findInput.select();\n this._findInput.focus();\n }\n }, 50);\n }\n\n // ---------------------------------------------------------------------------\n // Open / close\n // ---------------------------------------------------------------------------\n\n _open() {\n if (!this._dialog) return;\n // If already visible, just focus the search input — don't re-trap.\n if (this._dialog.style.display === 'flex') {\n if (this._findInput) this._findInput.focus();\n return;\n }\n this._dialog.style.display = 'flex';\n // Release any previous trap before installing a new one.\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n this._removeTrap = trapFocus(this._dialog, () => this._close());\n }\n\n _close() {\n this._clearHighlights();\n if (this._dialog) this._dialog.style.display = 'none';\n if (this._removeTrap) { this._removeTrap(); this._removeTrap = null; }\n // Return focus to the editor\n this.context.invoke('editor.focus');\n }\n\n _updateMode() {\n if (!this._dialog) return;\n const replaceRow = this._dialog.querySelector('.an-fr-replace-row');\n const replaceActions = this._dialog.querySelector('.an-fr-replace-actions');\n const title = this._dialog.querySelector('.an-dialog-title');\n\n const isReplace = this._mode === 'replace';\n if (replaceRow) replaceRow.style.display = isReplace ? '' : 'none';\n if (replaceActions) replaceActions.style.display = isReplace ? '' : 'none';\n if (title) title.textContent = isReplace ? this.context.locale.findReplace.findReplaceTitle : this.context.locale.findReplace.findTitle;\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.findReplace;\n const overlay = createElement('div', {\n class: 'an-dialog-overlay an-fr-dialog',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': L.findReplaceTitle,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n // ---- Title row ----\n const titleRow = createElement('div', { class: 'an-icon-title-row' });\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.findTitle;\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n 'aria-label': 'Close',\n });\n closeBtn.textContent = L.close;\n this._closeBtn = closeBtn;\n titleRow.append(title, closeBtn);\n box.appendChild(titleRow);\n\n // ---- Find row ----\n const findRow = createElement('div', { class: 'an-fr-find-row' });\n const findInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.findPlaceholder,\n 'aria-label': L.searchAriaLabel,\n });\n this._findInput = findInput;\n findRow.appendChild(findInput);\n box.appendChild(findRow);\n\n // ---- Options row (case-sensitive toggle + match counter) ----\n const optRow = createElement('div', { class: 'an-fr-options-row' });\n const caseLabel = createElement('label', { class: 'an-label an-label-inline' });\n const caseCheckbox = createElement('input', {\n type: 'checkbox',\n 'aria-label': 'Case sensitive',\n });\n this._caseCheckbox = caseCheckbox;\n caseLabel.append(caseCheckbox, document.createTextNode(L.caseSensitive));\n const counter = createElement('span', { class: 'an-fr-counter' });\n this._counterEl = counter;\n optRow.append(caseLabel, counter);\n box.appendChild(optRow);\n\n // ---- Find actions ----\n const findActions = createElement('div', { class: 'an-dialog-actions an-fr-find-actions' });\n const prevBtn = createElement('button', { type: 'button', class: 'an-btn' });\n prevBtn.textContent = L.prevBtn;\n const nextBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n nextBtn.textContent = L.nextBtn;\n findActions.append(prevBtn, nextBtn);\n box.appendChild(findActions);\n\n // ---- Replace row (hidden by default) ----\n const replaceRow = createElement('div', { class: 'an-fr-replace-row' });\n replaceRow.style.display = 'none';\n const replaceInput = createElement('input', {\n type: 'text',\n class: 'an-input',\n placeholder: L.replacePlaceholder,\n 'aria-label': L.replaceAriaLabel,\n });\n this._replaceInput = replaceInput;\n replaceRow.appendChild(replaceInput);\n box.appendChild(replaceRow);\n\n // ---- Replace actions (hidden by default) ----\n const replaceActions = createElement('div', { class: 'an-dialog-actions an-fr-replace-actions' });\n replaceActions.style.display = 'none';\n const replaceBtn = createElement('button', { type: 'button', class: 'an-btn' });\n replaceBtn.textContent = L.replaceBtn;\n const replaceAllBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });\n replaceAllBtn.textContent = L.replaceAllBtn;\n replaceActions.append(replaceBtn, replaceAllBtn);\n box.appendChild(replaceActions);\n\n overlay.appendChild(box);\n\n // ---- Event bindings ----\n const d1 = on(closeBtn, 'click', () => this._close());\n const d2 = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n const d3 = on(findInput, 'input', () => this._onSearch());\n const d4 = on(caseCheckbox, 'change', () => {\n this._caseSensitive = caseCheckbox.checked;\n this._onSearch();\n });\n const d5 = on(nextBtn, 'click', () => this._next());\n const d6 = on(prevBtn, 'click', () => this._prev());\n const d7 = on(replaceBtn, 'click', () => this._replace());\n const d8 = on(replaceAllBtn, 'click', () => this._replaceAll());\n const d9 = on(findInput, 'keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.shiftKey ? this._prev() : this._next();\n }\n });\n const d10 = on(replaceInput, 'keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._replace();\n }\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Search logic\n // ---------------------------------------------------------------------------\n\n _onSearch() {\n this._clearHighlights();\n const query = this._findInput ? this._findInput.value : '';\n if (!query) {\n this._updateCounter();\n return;\n }\n this._findAndHighlight(query);\n this._updateCounter();\n }\n\n /**\n * Finds all occurrences of `query` in the editable area text nodes,\n * then wraps each match in a <mark class=\"an-highlight\"> element.\n * Iterates text nodes in reverse so earlier offsets remain valid.\n * @param {string} query\n */\n _findAndHighlight(query) {\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n\n // Collect raw matches: { node, start, end }\n const rawMatches = this._findRawMatches(query, editable);\n if (rawMatches.length === 0) return;\n\n this._currentIndex = 0;\n\n // Wrap matches in reverse order so earlier text offsets stay valid when\n // later sections of the same text node are split by surroundContents().\n // Use push() instead of unshift() to avoid O(n²) shifting on every insert;\n // reverse() at the end restores forward document order in O(n).\n for (let i = rawMatches.length - 1; i >= 0; i--) {\n const { node, start, end } = rawMatches[i];\n try {\n const range = document.createRange();\n range.setStart(node, start);\n range.setEnd(node, end);\n const mark = document.createElement('mark');\n mark.className = 'an-highlight';\n range.surroundContents(mark);\n this._matches.push({ mark });\n } catch (_) {\n // surroundContents fails when the range crosses element boundaries.\n // This can happen with <br> inside matched text — skip safely.\n this._matches.push({ mark: null });\n }\n }\n this._matches.reverse(); // O(n) — restore forward document order\n\n // Drop entries where wrapping failed so the counter and navigation are accurate\n this._matches = this._matches.filter((m) => m.mark);\n if (this._matches.length === 0) return;\n\n // Highlight the first (current) match\n if (this._matches[0] && this._matches[0].mark) {\n this._matches[0].mark.className = 'an-highlight an-highlight-current';\n this._matches[0].mark.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n }\n\n /**\n * Walks all text nodes under `root` and returns positional match descriptors.\n * @param {string} query\n * @param {HTMLElement} root\n * @returns {{ node: Text, start: number, end: number }[]}\n */\n _findRawMatches(query, root) {\n const results = [];\n // Reuse compiled regex when query and case-sensitivity haven't changed\n if (this._lastQuery !== query || this._lastCaseSensitive !== this._caseSensitive) {\n const flags = this._caseSensitive ? 'g' : 'gi';\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n this._queryRegex = new RegExp(escaped, flags);\n this._lastQuery = query;\n this._lastCaseSensitive = this._caseSensitive;\n }\n const re = this._queryRegex;\n\n const walker = document.createTreeWalker(root, 0x4 /* NodeFilter.SHOW_TEXT */);\n let node;\n while ((node = walker.nextNode())) {\n re.lastIndex = 0;\n let m;\n while ((m = re.exec(node.textContent)) !== null) {\n results.push({ node, start: m.index, end: m.index + m[0].length });\n }\n }\n return results;\n }\n\n // ---------------------------------------------------------------------------\n // Navigation\n // ---------------------------------------------------------------------------\n\n _next() {\n if (this._matches.length === 0) return;\n this._currentIndex = (this._currentIndex + 1) % this._matches.length;\n this._scrollToMatch(this._currentIndex);\n this._updateCounter();\n }\n\n _prev() {\n if (this._matches.length === 0) return;\n this._currentIndex = (this._currentIndex - 1 + this._matches.length) % this._matches.length;\n this._scrollToMatch(this._currentIndex);\n this._updateCounter();\n }\n\n _scrollToMatch(index) {\n const match = this._matches[index];\n if (!match || !match.mark) return;\n // Update CSS classes\n this._matches.forEach((m, i) => {\n if (m.mark) {\n m.mark.className = i === index\n ? 'an-highlight an-highlight-current'\n : 'an-highlight';\n }\n });\n match.mark.scrollIntoView({ block: 'center', behavior: 'smooth' });\n }\n\n // ---------------------------------------------------------------------------\n // Replace\n // ---------------------------------------------------------------------------\n\n _replace() {\n if (this._matches.length === 0 || this._currentIndex < 0) return;\n const match = this._matches[this._currentIndex];\n if (!match || !match.mark || !match.mark.parentNode) return;\n\n const replacement = this._replaceInput ? this._replaceInput.value : '';\n const parent = match.mark.parentNode;\n const textNode = document.createTextNode(replacement);\n parent.insertBefore(textNode, match.mark);\n parent.removeChild(match.mark);\n parent.normalize();\n this.context.invoke('editor.afterCommand');\n const savedIndex = this._currentIndex;\n this._onSearch();\n if (this._matches.length > 0) {\n this._currentIndex = Math.min(savedIndex, this._matches.length - 1);\n this._scrollToMatch(this._currentIndex);\n this._updateCounter();\n }\n }\n\n _replaceAll() {\n if (this._matches.length === 0) return;\n const replacement = this._replaceInput ? this._replaceInput.value : '';\n\n this._matches.forEach(({ mark }) => {\n if (!mark || !mark.parentNode) return;\n const textNode = document.createTextNode(replacement);\n mark.parentNode.insertBefore(textNode, mark);\n mark.parentNode.removeChild(mark);\n });\n\n if (this.context.layoutInfo.editable) {\n this.context.layoutInfo.editable.normalize();\n }\n this._matches = [];\n this._currentIndex = -1;\n this.context.invoke('editor.afterCommand');\n this._onSearch();\n }\n\n // ---------------------------------------------------------------------------\n // Highlight management\n // ---------------------------------------------------------------------------\n\n /**\n * Removes all <mark class=\"an-highlight\"> elements from the editable area,\n * restoring the original text nodes via normalization.\n */\n _clearHighlights() {\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n\n editable.querySelectorAll('mark.an-highlight').forEach((mark) => {\n const parent = mark.parentNode;\n if (!parent) return;\n while (mark.firstChild) parent.insertBefore(mark.firstChild, mark);\n parent.removeChild(mark);\n });\n // Merge adjacent text nodes after unwrapping\n editable.normalize();\n\n this._matches = [];\n this._currentIndex = -1;\n }\n\n // ---------------------------------------------------------------------------\n // Counter display\n // ---------------------------------------------------------------------------\n\n _updateCounter() {\n if (!this._counterEl) return;\n const total = this._matches.length;\n if (total === 0) {\n const query = this._findInput ? this._findInput.value : '';\n this._counterEl.textContent = query ? 'No results' : '';\n } else {\n this._counterEl.textContent = `${this._currentIndex + 1} / ${total}`;\n }\n }\n}\n","// ImageCropOverlay.js - Inline crop overlay for images inside the editor\n//\n// Architecture:\n// - A dark scrim fills the entire viewport (fixed, z=10100) with a transparent\n// cutout showing the current crop region (clip-path technique).\n// - A \"crop box\" div overlaps the cutout; four corner + four edge handles let\n// the user drag to resize it.\n// - On Confirm: draws the crop region onto an off-screen canvas and replaces\n// img.src with a data-URL. Cross-origin images are caught and a warning is\n// shown instead of crashing.\n// - All pointer listeners are document-level and are torn down after each\n// interaction to avoid leaks.\n\nimport { on } from '../core/dom.js';\n\n// Minimum crop box dimension in CSS pixels\nconst MIN_SIZE = 20;\n\n// Accent colour for handles (synced with $an-primary)\nconst ACCENT = '#3b82f6';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Clamp `value` between `lo` and `hi`. */\nconst clamp = (value, lo, hi) => Math.min(Math.max(value, lo), hi);\n\n/**\n * Attempt to draw `img` onto a canvas even if it was loaded without CORS.\n * Returns a canvas element on success, or null if the image is cross-origin\n * tainted and cannot be read.\n *\n * Strategy:\n * 1. Try directly — works for same-origin and data/blob URLs.\n * 2. Re-load with crossOrigin=\"anonymous\" and retry (needs server ACAO header).\n *\n * @param {HTMLImageElement} img\n * @param {DOMRect} naturalRect - crop region in *natural* image pixels\n * @param {number} renderW - desired output width\n * @param {number} renderH - desired output height\n * @returns {Promise<HTMLCanvasElement|null>}\n */\nfunction drawCropToCanvas(img, naturalRect, renderW, renderH) {\n return new Promise((resolve) => {\n const tryDraw = (source) => {\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(renderW);\n canvas.height = Math.round(renderH);\n const ctx = canvas.getContext('2d');\n try {\n ctx.drawImage(\n source,\n naturalRect.x, naturalRect.y, naturalRect.width, naturalRect.height,\n 0, 0, canvas.width, canvas.height,\n );\n // Access a pixel — this throws if canvas is tainted\n ctx.getImageData(0, 0, 1, 1);\n resolve(canvas);\n } catch (_) {\n resolve(null);\n }\n };\n\n // Fast path — data: / blob: / same-origin\n if (\n img.src.startsWith('data:') ||\n img.src.startsWith('blob:') ||\n img.src.startsWith(window.location.origin)\n ) {\n tryDraw(img);\n return;\n }\n\n // Cross-origin: try a fresh image with crossOrigin=\"anonymous\"\n const tmp = new Image();\n tmp.crossOrigin = 'anonymous';\n tmp.onload = () => tryDraw(tmp);\n tmp.onerror = () => resolve(null);\n // Append cache-buster to avoid serving a cached non-CORS response\n tmp.src = img.src + (img.src.includes('?') ? '&' : '?') + '_an=' + Date.now();\n });\n}\n\n// ---------------------------------------------------------------------------\n// ImageCropOverlay\n// ---------------------------------------------------------------------------\n\nexport class ImageCropOverlay {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLImageElement|null} */\n this._img = null;\n /** Crop box position in viewport px: { x, y, w, h } */\n this._box = null;\n /** Natural-size bounding rect of the image in viewport px */\n this._imgRect = null;\n\n this._scrim = null;\n this._cropBox = null;\n this._handles = {};\n this._toolbar = null;\n this._infoEl = null;\n\n this._dragDisposers = null;\n this._disposers = [];\n }\n\n initialize() {\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n this._close(false);\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Open the crop overlay for the given image.\n * @param {HTMLImageElement} img\n */\n open(img) {\n if (this._scrim) this._close(false); // guard: only one at a time\n\n this._img = img;\n const rect = img.getBoundingClientRect();\n this._imgRect = rect;\n\n // Default crop box = full image, inset 12 px on each side (feels visual)\n const inset = Math.min(12, rect.width * 0.1, rect.height * 0.1);\n this._box = {\n x: rect.left + inset,\n y: rect.top + inset,\n w: rect.width - inset * 2,\n h: rect.height - inset * 2,\n };\n\n this._buildDOM();\n this._updateDOM();\n this._bindEsc();\n }\n\n // ---------------------------------------------------------------------------\n // DOM construction\n // ---------------------------------------------------------------------------\n\n _buildDOM() {\n /* ---- scrim ---- */\n const scrim = document.createElement('div');\n scrim.className = 'an-crop-scrim';\n // Prevent scroll during crop\n scrim.style.cssText = `\n position:fixed; inset:0; z-index:10100;\n cursor:crosshair;\n background: rgba(0,0,0,0.55);\n `;\n // Click on scrim (outside crop box) → cancel\n this._disposers.push(\n on(scrim, 'mousedown', (e) => {\n if (e.target === scrim) this._close(false);\n }),\n );\n\n /* ---- crop box ---- */\n const cropBox = document.createElement('div');\n cropBox.className = 'an-crop-box';\n cropBox.style.cssText = `\n position:fixed; z-index:10101;\n box-sizing:border-box;\n border:2px solid ${ACCENT};\n cursor:move;\n outline: none;\n `;\n\n /* ---- rule-of-thirds grid lines ---- */\n const grid = document.createElement('div');\n grid.className = 'an-crop-grid';\n grid.style.cssText = `\n position:absolute; inset:0; pointer-events:none;\n opacity:0.35;\n `;\n // 2 vertical + 2 horizontal lines\n ['33.33%','66.66%'].forEach((pos) => {\n const vl = document.createElement('div');\n vl.style.cssText = `position:absolute;top:0;bottom:0;left:${pos};width:1px;background:#fff;`;\n const hl = document.createElement('div');\n hl.style.cssText = `position:absolute;left:0;right:0;top:${pos};height:1px;background:#fff;`;\n grid.appendChild(vl);\n grid.appendChild(hl);\n });\n cropBox.appendChild(grid);\n\n /* ---- resize handles ---- */\n const HANDLE_DEFS = [\n { id: 'nw', cur: 'nw-resize', top: '-5px', left: '-5px' },\n { id: 'n', cur: 'n-resize', top: '-5px', left: 'calc(50% - 5px)' },\n { id: 'ne', cur: 'ne-resize', top: '-5px', right: '-5px' },\n { id: 'e', cur: 'e-resize', top: 'calc(50% - 5px)', right: '-5px' },\n { id: 'se', cur: 'se-resize', bottom: '-5px', right: '-5px' },\n { id: 's', cur: 's-resize', bottom: '-5px', left: 'calc(50% - 5px)' },\n { id: 'sw', cur: 'sw-resize', bottom: '-5px', left: '-5px' },\n { id: 'w', cur: 'w-resize', top: 'calc(50% - 5px)', left: '-5px' },\n ];\n\n HANDLE_DEFS.forEach(({ id, cur, ...pos }) => {\n const h = document.createElement('div');\n h.className = `an-crop-handle an-crop-handle-${id}`;\n h.style.cssText = [\n 'position:absolute',\n 'width:10px', 'height:10px',\n `background:${ACCENT}`,\n 'border:2px solid #fff',\n 'border-radius:2px',\n 'box-sizing:border-box',\n `cursor:${cur}`,\n ...Object.entries(pos).map(([k, v]) => `${k}:${v}`),\n ].join(';');\n this._disposers.push(\n on(h, 'mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startHandleDrag(e, id);\n }),\n );\n this._handles[id] = h;\n cropBox.appendChild(h);\n });\n\n /* ---- crop move drag ---- */\n this._disposers.push(\n on(cropBox, 'mousedown', (e) => {\n // Only directly on the box surface (not on a handle)\n if (e.target !== cropBox && e.target !== grid && !(e.target.tagName === 'DIV' && !e.target.className.includes('handle'))) {\n // Let handle mousedown handle it\n return;\n }\n if (e.target.className && e.target.className.includes('an-crop-handle')) return;\n e.preventDefault();\n e.stopPropagation();\n this._startBoxMove(e);\n }),\n );\n\n /* ---- info label ---- */\n const infoEl = document.createElement('div');\n infoEl.className = 'an-crop-info';\n infoEl.style.cssText = `\n position:absolute; bottom:-28px; left:0;\n font:bold 11px/20px system-ui,sans-serif;\n color:#fff; white-space:nowrap;\n pointer-events:none;\n text-shadow: 0 1px 3px rgba(0,0,0,.6);\n `;\n cropBox.appendChild(infoEl);\n this._infoEl = infoEl;\n\n /* ---- floating toolbar ---- */\n const toolbar = document.createElement('div');\n toolbar.className = 'an-crop-toolbar';\n toolbar.style.cssText = `\n position:fixed; z-index:10102;\n background:#1e1e2e; border-radius:6px;\n padding:5px 8px; display:flex; gap:6px;\n align-items:center;\n box-shadow:0 4px 16px rgba(0,0,0,.4);\n font:13px system-ui,sans-serif;\n `;\n\n const confirmBtn = this._makeToolbarBtn('✓ Crop', '#22c55e', () => this._confirm());\n const cancelBtn = this._makeToolbarBtn('✕ Cancel', '#94a3b8', () => this._close(false));\n\n // Aspect ratio lock checkbox\n const arLabel = document.createElement('label');\n arLabel.style.cssText = 'color:#94a3b8;font-size:11px;cursor:pointer;display:flex;align-items:center;gap:4px;';\n const arCheck = document.createElement('input');\n arCheck.type = 'checkbox';\n arCheck.style.accentColor = ACCENT;\n arLabel.appendChild(arCheck);\n arLabel.appendChild(document.createTextNode('Lock ratio'));\n this._arCheck = arCheck;\n\n toolbar.appendChild(confirmBtn);\n toolbar.appendChild(cancelBtn);\n toolbar.appendChild(arLabel);\n this._toolbar = toolbar;\n\n // Prevent toolbar clicks from closing the overlay\n this._disposers.push(\n on(toolbar, 'mousedown', (e) => e.stopPropagation()),\n );\n\n document.body.appendChild(scrim);\n document.body.appendChild(cropBox);\n document.body.appendChild(toolbar);\n\n this._scrim = scrim;\n this._cropBox = cropBox;\n }\n\n _makeToolbarBtn(text, color, handler) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.textContent = text;\n btn.style.cssText = `\n background:none; border:1px solid ${color}; border-radius:4px;\n color:${color}; padding:3px 10px; cursor:pointer; font-size:12px;\n font-family:inherit;\n transition:background 0.12s;\n `;\n btn.addEventListener('mouseover', () => { btn.style.background = color + '22'; });\n btn.addEventListener('mouseout', () => { btn.style.background = 'none'; });\n this._disposers.push(on(btn, 'click', (e) => { e.stopPropagation(); handler(); }));\n return btn;\n }\n\n // ---------------------------------------------------------------------------\n // DOM sync\n // ---------------------------------------------------------------------------\n\n _updateDOM() {\n const { x, y, w, h } = this._box;\n\n this._cropBox.style.left = `${x}px`;\n this._cropBox.style.top = `${y}px`;\n this._cropBox.style.width = `${w}px`;\n this._cropBox.style.height = `${h}px`;\n\n // Scrim cutout via clip-path polygon (punches a transparent hole)\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n // Outer rect → inner rectangle (counterclockwise) = hole\n this._scrim.style.clipPath = [\n `polygon(`,\n `0 0, ${vw}px 0, ${vw}px ${vh}px, 0 ${vh}px, 0 0,`,\n `${x}px ${y}px, ${x}px ${y + h}px, ${x + w}px ${y + h}px, ${x + w}px ${y}px, ${x}px ${y}px`,\n `)`,\n ].join('');\n\n // Info label: natural pixels\n if (this._img) {\n const nw = this._img.naturalWidth || 0;\n const nh = this._img.naturalHeight || 0;\n const dispW = this._imgRect.width || 1;\n const dispH = this._imgRect.height || 1;\n const scale = { x: nw / dispW, y: nh / dispH };\n const cx = clamp(x - this._imgRect.left, 0, dispW);\n const cy = clamp(y - this._imgRect.top, 0, dispH);\n const cw = clamp(w, 0, dispW - cx);\n const ch = clamp(h, 0, dispH - cy);\n this._infoEl.textContent = `${Math.round(cw * scale.x)} × ${Math.round(ch * scale.y)} px`;\n }\n\n // Position toolbar below crop box (or above if near bottom)\n const margin = 8;\n let tbTop = y + h + margin;\n if (tbTop + 40 > window.innerHeight - margin) tbTop = y - 40 - margin;\n this._toolbar.style.left = `${x}px`;\n this._toolbar.style.top = `${tbTop}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Drag: move box\n // ---------------------------------------------------------------------------\n\n _startBoxMove(e) {\n const startX = e.clientX - this._box.x;\n const startY = e.clientY - this._box.y;\n const r = this._imgRect;\n\n const onMove = (me) => {\n this._box.x = clamp(me.clientX - startX, r.left, r.right - this._box.w);\n this._box.y = clamp(me.clientY - startY, r.top, r.bottom - this._box.h);\n this._updateDOM();\n };\n\n this._attachDocDrag(onMove);\n }\n\n // ---------------------------------------------------------------------------\n // Drag: resize handle\n // ---------------------------------------------------------------------------\n\n _startHandleDrag(e, id) {\n const startX = e.clientX;\n const startY = e.clientY;\n const orig = { ...this._box };\n const r = this._imgRect;\n const lockAR = this._arCheck && this._arCheck.checked;\n const aspect = orig.w / (orig.h || 1);\n\n const onMove = (me) => {\n const dx = me.clientX - startX;\n const dy = me.clientY - startY;\n let { x, y, w, h } = orig;\n\n // Apply deltas per handle position\n if (id.includes('e')) w = Math.max(MIN_SIZE, orig.w + dx);\n if (id.includes('s')) h = Math.max(MIN_SIZE, orig.h + dy);\n if (id.includes('w')) { x = Math.min(orig.x + orig.w - MIN_SIZE, orig.x + dx); w = orig.x + orig.w - x; }\n if (id.includes('n')) { y = Math.min(orig.y + orig.h - MIN_SIZE, orig.y + dy); h = orig.y + orig.h - y; }\n\n // Aspect-ratio lock (corner handles)\n if (lockAR && id.length === 2) {\n if (Math.abs(dx) >= Math.abs(dy)) {\n h = w / aspect;\n if (id.includes('n')) y = orig.y + orig.h - h;\n } else {\n w = h * aspect;\n if (id.includes('w')) x = orig.x + orig.w - w;\n }\n }\n\n // Clamp to image bounds\n x = clamp(x, r.left, r.right - MIN_SIZE);\n y = clamp(y, r.top, r.bottom - MIN_SIZE);\n w = clamp(w, MIN_SIZE, r.right - x);\n h = clamp(h, MIN_SIZE, r.bottom - y);\n\n this._box = { x, y, w, h };\n this._updateDOM();\n };\n\n this._attachDocDrag(onMove);\n }\n\n /**\n * Attach mousemove + mouseup to document for the duration of a drag.\n * @param {(e: MouseEvent) => void} onMove\n */\n _attachDocDrag(onMove) {\n const cleanup = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', cleanup);\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n };\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', cleanup, { once: true });\n }\n\n // ---------------------------------------------------------------------------\n // Keyboard\n // ---------------------------------------------------------------------------\n\n _bindEsc() {\n const handler = (e) => {\n if (e.key === 'Escape') { e.preventDefault(); this._close(false); }\n if (e.key === 'Enter') { e.preventDefault(); this._confirm(); }\n };\n document.addEventListener('keydown', handler);\n this._disposers.push(() => document.removeEventListener('keydown', handler));\n }\n\n // ---------------------------------------------------------------------------\n // Confirm / Close\n // ---------------------------------------------------------------------------\n\n async _confirm() {\n const img = this._img;\n if (!img) { this._close(false); return; }\n\n const r = this._imgRect;\n const { x, y, w, h } = this._box;\n\n // Convert display-px crop region → natural-px\n const scaleX = (img.naturalWidth || img.width || 1) / (r.width || 1);\n const scaleY = (img.naturalHeight || img.height || 1) / (r.height || 1);\n\n const natX = Math.round(clamp(x - r.left, 0, r.width) * scaleX);\n const natY = Math.round(clamp(y - r.top, 0, r.height) * scaleY);\n const natW = Math.round(clamp(w, 0, r.width - (x - r.left)) * scaleX);\n const natH = Math.round(clamp(h, 0, r.height - (y - r.top)) * scaleY);\n\n if (natW <= 0 || natH <= 0) { this._close(false); return; }\n\n // Output dimensions = display-pixel crop size (preserve visual size)\n const outW = w;\n const outH = h;\n\n const naturalRect = { x: natX, y: natY, width: natW, height: natH };\n const canvas = await drawCropToCanvas(img, naturalRect, outW, outH);\n\n if (!canvas) {\n // Cross-origin failure — inform user and abort\n window.alert(\n 'Cannot crop this image: the image server does not allow cross-origin access.\\n' +\n 'Upload the image directly to use the crop tool.',\n );\n this._close(false);\n return;\n }\n\n // Determine output format: preserve JPEG, fall back to PNG\n const fmt = img.src.match(/^data:image\\/(jpe?g)/i) ? 'image/jpeg' : 'image/png';\n const quality = fmt === 'image/jpeg' ? 0.92 : undefined;\n const newSrc = canvas.toDataURL(fmt, quality);\n\n // Apply the crop\n this._close(false);\n\n img.src = newSrc;\n // Strip explicit width/height — the image should show at its new natural size\n img.style.width = '';\n img.style.height = '';\n img.removeAttribute('width');\n img.removeAttribute('height');\n\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n }\n\n /**\n * Remove all overlay DOM elements and reset state.\n * @param {boolean} _committed - reserved for future use\n */\n _close(_committed) {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n [this._scrim, this._cropBox, this._toolbar].forEach((el) => {\n if (el && el.parentNode) el.parentNode.removeChild(el);\n });\n\n this._scrim = null;\n this._cropBox = null;\n this._toolbar = null;\n this._infoEl = null;\n this._handles = {};\n this._img = null;\n this._box = null;\n this._imgRect = null;\n this._arCheck = null;\n }\n}\n","/**\n * AutoSaveRestore.js — Detects a previously auto-saved draft and offers the\n * user a banner to restore or discard it.\n *\n * Activated when both `autoSave` and `autoSaveRestore` options are true.\n * On initialize it checks localStorage for a draft that is within the\n * `autoSaveRestoreTimeout` day window. If one is found a dismissible banner\n * is prepended to the editor container.\n */\n\nexport class AutoSaveRestore {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n\n /** @type {HTMLElement|null} */\n this._banner = null;\n }\n\n initialize() {\n if (!this.options.autoSave || !this.options.autoSaveRestore) return this;\n\n const key = this.options.autoSaveKey;\n const metaKey = key + ':asrmeta';\n\n let saved;\n let meta;\n try {\n saved = localStorage.getItem(key);\n meta = JSON.parse(localStorage.getItem(metaKey) || '{}');\n } catch (_) {\n return this;\n }\n\n if (!saved) return this;\n\n const timeout = this.options.autoSaveRestoreTimeout;\n if (timeout > 0) {\n const ageMs = Date.now() - (meta.savedAt || 0);\n if (ageMs > timeout * 86400000) {\n try { localStorage.removeItem(key); localStorage.removeItem(metaKey); } catch (_) {}\n return this;\n }\n }\n\n this._showBanner(saved, meta);\n return this;\n }\n\n destroy() {\n this._removeBanner();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n _showBanner(draftHtml, meta) {\n const locale = this.context.locale;\n const t = locale.autoSaveRestore || {};\n const label = t.found || 'Draft found. Restore?';\n const restoreLabel = t.restore || 'Restore';\n const discardLabel = t.discard || 'Discard';\n\n const banner = document.createElement('div');\n banner.className = 'an-asr-banner';\n banner.setAttribute('role', 'alert');\n\n const msg = document.createElement('span');\n msg.className = 'an-asr-msg';\n if (meta.savedAt) {\n const d = new Date(meta.savedAt);\n const formatted = d.toLocaleString();\n msg.textContent = (t.foundAt || 'Draft from {date}. Restore?').replace('{date}', formatted);\n } else {\n msg.textContent = label;\n }\n\n const restoreBtn = document.createElement('button');\n restoreBtn.type = 'button';\n restoreBtn.className = 'an-btn an-asr-btn-restore';\n restoreBtn.textContent = restoreLabel;\n restoreBtn.addEventListener('click', () => this._restore(draftHtml));\n\n const discardBtn = document.createElement('button');\n discardBtn.type = 'button';\n discardBtn.className = 'an-btn an-asr-btn-discard';\n discardBtn.textContent = discardLabel;\n discardBtn.addEventListener('click', () => this._discard());\n\n banner.appendChild(msg);\n banner.appendChild(restoreBtn);\n banner.appendChild(discardBtn);\n\n this._banner = banner;\n const container = this.context.layoutInfo.container;\n container.insertBefore(banner, container.firstChild);\n }\n\n _restore(draftHtml) {\n this.context.setHTML(draftHtml);\n this.context.clearHistory();\n this._removeBanner();\n\n if (typeof this.options.onAutoSaveRestore === 'function') {\n this.options.onAutoSaveRestore(draftHtml, this.context);\n }\n }\n\n _discard() {\n const key = this.options.autoSaveKey;\n try {\n localStorage.removeItem(key);\n localStorage.removeItem(key + ':asrmeta');\n } catch (_) {}\n this._removeBanner();\n }\n\n _removeBanner() {\n if (this._banner && this._banner.parentNode) {\n this._banner.parentNode.removeChild(this._banner);\n }\n this._banner = null;\n }\n}\n","/**\n * MarkdownShortcuts.js — Convert Markdown-style syntax typed directly in the\n * editor into rich HTML elements (input rules / auto-format).\n *\n * Activated when `markdownShortcuts: true` (the default).\n *\n * Block rules — triggered by Space or Enter at the start of a line:\n * #[#[#]]· → H1 / H2 / H3\n * >· → blockquote\n * -· or *· → unordered list item\n * 1.· → ordered list item\n * [ ]· → checklist item\n * --- → horizontal rule (on Enter)\n * ``` → code block (on Enter)\n *\n * Inline rules — triggered when the closing marker is typed:\n * **text** → <strong>\n * *text* → <em>\n * ~~text~~ → <s>\n * `code` → <code>\n */\n\nimport { on } from '../core/dom.js';\n\nexport class MarkdownShortcuts {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n }\n\n initialize() {\n if (!this.options.markdownShortcuts) return this;\n const editable = this.context.layoutInfo.editable;\n const d1 = on(editable, 'keydown', /** @param {KeyboardEvent} e */ (e) => this._onKeydown(e));\n const d2 = on(editable, 'input', () => this._onInput());\n this._disposers.push(d1, d2);\n return this;\n }\n\n destroy() {\n this._disposers.forEach((d) => d());\n this._disposers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Block rules (Space / Enter)\n // ---------------------------------------------------------------------------\n\n _onKeydown(e) {\n if (e.key === ' ') {\n if (this._applyBlockRule()) e.preventDefault();\n } else if (e.key === 'Enter') {\n if (this._applyEnterRule()) e.preventDefault();\n }\n }\n\n /**\n * Returns the plain text of the line the cursor is on, up to the cursor.\n * @returns {{ text: string, range: Range, lineNode: Node } | null}\n */\n _getLineContext() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n if (!range.collapsed) return null;\n\n const editable = this.context.layoutInfo.editable;\n if (!editable.contains(range.startContainer)) return null;\n\n // Walk up to find the block-level ancestor inside the editable\n let node = range.startContainer;\n while (node && node !== editable && !this._isBlock(node)) {\n node = node.parentNode;\n }\n if (!node || node === editable) node = range.startContainer;\n\n // Collect all text content before the cursor within that block\n const tmpRange = document.createRange();\n tmpRange.setStart(node, 0);\n tmpRange.setEnd(range.startContainer, range.startOffset);\n const text = tmpRange.toString();\n\n return { text, range, lineNode: node };\n }\n\n _isBlock(node) {\n if (node.nodeType !== Node.ELEMENT_NODE) return false;\n const display = window.getComputedStyle(node).display;\n return display === 'block' || display === 'list-item' || display === 'table-cell';\n }\n\n /** Applies block rule on Space key. Returns true if a rule fired. */\n _applyBlockRule() {\n const ctx = this._getLineContext();\n if (!ctx) return false;\n const { text } = ctx;\n\n const blockPatterns = [\n { re: /^(#{1,3})$/, handler: (m) => this._convertToHeading(m[1].length) },\n { re: /^>$/, handler: () => this._convertToBlockquote() },\n { re: /^[-*]$/, handler: () => this._convertToList('ul') },\n { re: /^1\\.$/, handler: () => this._convertToList('ol') },\n { re: /^\\[ \\]$/, handler: () => this._convertToChecklist() },\n ];\n\n for (const { re, handler } of blockPatterns) {\n const m = text.match(re);\n if (m) {\n handler(m);\n return true;\n }\n }\n return false;\n }\n\n /** Applies block rule on Enter key (---, ```). Returns true if a rule fired. */\n _applyEnterRule() {\n const ctx = this._getLineContext();\n if (!ctx) return false;\n const { text } = ctx;\n\n if (/^-{3,}$/.test(text)) {\n this._convertToHr();\n return true;\n }\n if (/^`{3}/.test(text)) {\n this._convertToCodeBlock();\n return true;\n }\n return false;\n }\n\n // ---------------------------------------------------------------------------\n // Block converters\n // ---------------------------------------------------------------------------\n\n _selectLineAndDelete() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n // Select from the start of the block to the cursor and delete\n const startRange = document.createRange();\n startRange.setStart(range.startContainer.parentNode || range.startContainer, 0);\n startRange.setEnd(range.startContainer, range.startOffset);\n startRange.deleteContents();\n }\n\n _convertToHeading(level) {\n this._selectLineAndDelete();\n document.execCommand('formatBlock', false, `h${level}`);\n this.context.triggerEvent('change', this.context.getHTML());\n }\n\n _convertToBlockquote() {\n this._selectLineAndDelete();\n document.execCommand('formatBlock', false, 'blockquote');\n this.context.triggerEvent('change', this.context.getHTML());\n }\n\n _convertToList(type) {\n this._selectLineAndDelete();\n document.execCommand(type === 'ul' ? 'insertUnorderedList' : 'insertOrderedList');\n this.context.triggerEvent('change', this.context.getHTML());\n }\n\n _convertToChecklist() {\n this._selectLineAndDelete();\n this.context.invoke('editor.checklist');\n this.context.triggerEvent('change', this.context.getHTML());\n }\n\n _convertToHr() {\n this._selectLineAndDelete();\n this.context.invoke('editor.insertHR');\n this.context.triggerEvent('change', this.context.getHTML());\n }\n\n _convertToCodeBlock() {\n this._selectLineAndDelete();\n document.execCommand('formatBlock', false, 'pre');\n this.context.triggerEvent('change', this.context.getHTML());\n }\n\n // ---------------------------------------------------------------------------\n // Inline rules (input event)\n // ---------------------------------------------------------------------------\n\n _onInput() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n if (!range.collapsed) return;\n\n const editable = this.context.layoutInfo.editable;\n if (!editable.contains(range.startContainer)) return;\n\n const node = range.startContainer;\n if (node.nodeType !== Node.TEXT_NODE) return;\n\n const text = node.textContent;\n const offset = range.startOffset;\n\n const inlineRules = [\n // **bold**\n { re: /\\*\\*(.+?)\\*\\*$/, tag: 'strong' },\n // *italic* (not part of **)\n { re: /(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)$/, tag: 'em' },\n // ~~strike~~\n { re: /~~(.+?)~~$/, tag: 's' },\n // `code`\n { re: /`([^`]+)`$/, tag: 'code' },\n ];\n\n const upToCursor = text.slice(0, offset);\n for (const { re, tag } of inlineRules) {\n const m = upToCursor.match(re);\n if (!m) continue;\n\n const matchStart = upToCursor.length - m[0].length;\n const matchEnd = offset;\n const innerText = m[1];\n\n // Replace matched text with formatted element\n const before = text.slice(0, matchStart);\n const after = text.slice(matchEnd);\n\n const el = document.createElement(tag);\n el.textContent = innerText;\n\n // Rebuild the text node and insert the element\n const beforeNode = document.createTextNode(before);\n const afterNode = document.createTextNode('' + after);\n\n const parent = node.parentNode;\n parent.insertBefore(beforeNode, node);\n parent.insertBefore(el, node);\n parent.insertBefore(afterNode, node);\n parent.removeChild(node);\n\n // Place cursor after the element (after the ZWS)\n const newRange = document.createRange();\n newRange.setStart(afterNode, 1);\n newRange.collapse(true);\n sel.removeAllRanges();\n sel.addRange(newRange);\n\n this.context.triggerEvent('change', this.context.getHTML());\n break;\n }\n }\n}\n","/**\n * BubbleToolbar.js — A mini floating toolbar that appears above the current\n * text selection, allowing quick access to common formatting actions without\n * reaching for the main toolbar.\n *\n * Activated when `bubbleToolbar: true`. The set of visible buttons is\n * controlled by `bubbleToolbarItems` (array of button name strings).\n *\n * Built-in names: 'bold', 'italic', 'underline', 'strikethrough',\n * 'link', 'foreColor', 'removeFormat', 'inlineCode'.\n * Any name not found in the built-in map is silently ignored.\n */\n\nimport { on } from '../core/dom.js';\n\n// Minimal SVG icon set — only what the bubble toolbar needs.\nconst _S = 'stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"';\nconst _svg = (p) =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" ${_S} style=\"display:block\">${p}</svg>`;\n\nconst _ICONS = {\n bold: _svg('<path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/>'),\n italic: _svg('<line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/>'),\n underline: _svg('<path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/>'),\n strikethrough: _svg('<path d=\"M17.3 12H6.7\"/><path d=\"M10 6.5C10 5.1 11.1 4 12.5 4c1.4 0 2.5 1.1 2.5 2.5 0 .8-.4 1.5-1 2\"/><path d=\"M14 17.5C14 19 12.9 20 11.5 20 10.1 20 9 18.9 9 17.5c0-.8.4-1.5 1-2\"/>'),\n link: _svg('<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>'),\n foreColor: _svg('<path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/>'),\n removeFormat: _svg('<path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/>'),\n inlineCode: _svg('<path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\"/><path d=\"M16 3h1a2 2 0 0 1 2 2v5c0 1.1.9 2 2 2a2 2 0 0 1-2 2v5a2 2 0 0 1-2 2h-1\"/>'),\n};\n\nconst _ACTIONS = {\n bold: (ctx) => ctx.invoke('editor.bold'),\n italic: (ctx) => ctx.invoke('editor.italic'),\n underline: (ctx) => ctx.invoke('editor.underline'),\n strikethrough: (ctx) => ctx.invoke('editor.strikethrough'),\n link: (ctx) => ctx.invoke('linkDialog.show'),\n foreColor: (ctx) => {\n const color = window.prompt('Text color (hex or name):', '#000000');\n if (color) ctx.invoke('editor.foreColor', color);\n },\n removeFormat: (ctx) => ctx.invoke('editor.removeFormat'),\n inlineCode: (ctx) => ctx.invoke('editor.inlineCode'),\n};\n\nconst _ACTIVE = {\n bold: () => document.queryCommandState('bold'),\n italic: () => document.queryCommandState('italic'),\n underline: () => document.queryCommandState('underline'),\n strikethrough: () => document.queryCommandState('strikeThrough'),\n};\n\nexport class BubbleToolbar {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n\n /** @type {HTMLElement|null} */\n this._el = null;\n this._visible = false;\n this._rafId = null;\n this._contextMenuOpen = false;\n this._disposers = [];\n\n this._onSelectionChange = this._onSelectionChange.bind(this);\n this._onMousedown = this._onMousedown.bind(this);\n this._onKeydown = this._onKeydown.bind(this);\n this._onContextMenu = this._onContextMenu.bind(this);\n }\n\n initialize() {\n if (!this.options.bubbleToolbar) return this;\n this._build();\n const d1 = on(document, 'selectionchange', this._onSelectionChange);\n const d2 = on(document, 'mousedown', this._onMousedown);\n const d3 = on(document, 'keydown', this._onKeydown);\n const d4 = on(document, 'contextmenu', this._onContextMenu);\n const d5 = this.context.on('contextMenu:show', () => {\n this._contextMenuOpen = true;\n this._hide();\n });\n const d6 = this.context.on('contextMenu:hide', () => {\n this._contextMenuOpen = false;\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6);\n return this;\n }\n\n destroy() {\n if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);\n this._el = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n cancelAnimationFrame(this._rafId);\n }\n\n // ---------------------------------------------------------------------------\n // Build\n // ---------------------------------------------------------------------------\n\n _build() {\n const el = document.createElement('div');\n el.className = 'an-bubble-toolbar';\n el.setAttribute('role', 'toolbar');\n el.setAttribute('aria-label', 'Formatting');\n\n const items = this.options.bubbleToolbarItems || ['bold', 'italic', 'underline', 'link', 'foreColor', 'removeFormat'];\n for (const name of items) {\n if (!_ICONS[name] || !_ACTIONS[name]) continue;\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'an-bubble-btn';\n btn.dataset.name = name;\n btn.setAttribute('aria-label', name);\n btn.innerHTML = _ICONS[name];\n btn.addEventListener('mousedown', (e) => {\n // Prevent mousedown from collapsing selection before click fires\n e.preventDefault();\n });\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.context.invoke('editor.focus');\n _ACTIONS[name](this.context);\n this.context.invoke('editor.afterCommand');\n this._syncActive();\n });\n el.appendChild(btn);\n }\n\n document.body.appendChild(el);\n this._el = el;\n }\n\n // ---------------------------------------------------------------------------\n // Show / hide\n // ---------------------------------------------------------------------------\n\n _show(rect) {\n if (!this._el) return;\n const el = this._el;\n\n // Measure while invisible — position:fixed so no scroll offset needed\n el.style.visibility = 'hidden';\n el.style.display = 'flex';\n\n const bw = el.offsetWidth;\n const bh = el.offsetHeight;\n const gap = 8;\n\n // Center horizontally above the selection; flip below if no room above\n let left = rect.left + rect.width / 2 - bw / 2;\n let top = rect.top - bh - gap;\n\n left = Math.max(8, Math.min(left, window.innerWidth - bw - 8));\n\n if (top < 8) {\n top = rect.bottom + gap;\n }\n\n el.style.top = `${top}px`;\n el.style.left = `${left}px`;\n el.style.visibility = '';\n\n this._syncActive();\n this._visible = true;\n }\n\n _hide() {\n if (!this._el) return;\n this._el.style.display = 'none';\n this._visible = false;\n }\n\n _syncActive() {\n if (!this._el) return;\n this._el.querySelectorAll('.an-bubble-btn').forEach((btn) => {\n const name = btn.dataset.name;\n const activeFn = _ACTIVE[name];\n btn.classList.toggle('an-active', !!(activeFn && activeFn()));\n });\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n _onSelectionChange() {\n cancelAnimationFrame(this._rafId);\n this._rafId = requestAnimationFrame(() => {\n if (this._contextMenuOpen) return;\n\n const sel = window.getSelection();\n if (!sel || sel.isCollapsed || !sel.rangeCount) {\n this._hide();\n return;\n }\n\n const editable = this.context.layoutInfo.editable;\n if (!editable.contains(sel.anchorNode)) {\n this._hide();\n return;\n }\n\n // Don't show inside code view or read-only\n if (this.context.options.readOnly) {\n this._hide();\n return;\n }\n\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n if (!rect || rect.width === 0) {\n this._hide();\n return;\n }\n\n this._show(rect);\n });\n }\n\n _onMousedown(e) {\n // Hide when clicking outside both the editable and the bubble toolbar\n if (!this._visible) return;\n if (this._el && this._el.contains(e.target)) return;\n const editable = this.context.layoutInfo.editable;\n if (editable.contains(e.target)) return;\n this._hide();\n }\n\n _onKeydown(e) {\n if (e.key === 'Escape' && this._visible) {\n this._hide();\n }\n }\n\n _onContextMenu() {\n // Hide immediately on right-click — contextMenu:show event will also set the flag,\n // but firing here prevents a one-frame flicker before the event propagates.\n this._hide();\n }\n}\n","/**\n * Mention.js — @mention autocomplete support.\n *\n * Activated when `mention.onSearch` option is provided.\n *\n * When the user types the trigger character (default `@`) followed by at least\n * `mention.minChars` characters, `onSearch(query, callback)` is called.\n * The callback receives an array of `{ id, label, avatar? }` items which are\n * rendered in a floating dropdown. Selecting an item inserts a non-editable\n * mention chip and fires `onInsert` (if provided) to override the default HTML.\n *\n * Options shape (passed as `mention` option object):\n * {\n * trigger: '@',\n * minChars: 1,\n * maxResults: 8,\n * debounce: 200,\n * onSearch: (query, callback) => void,\n * onInsert: (item) => string | null,\n * mentionClass: 'an-mention',\n * allowSpaces: false,\n * }\n */\n\nimport { on } from '../core/dom.js';\n\nexport class Mention {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n\n /** @type {HTMLElement|null} */\n this._dropdown = null;\n /** @type {string} */\n this._query = '';\n /** @type {number|null} */\n this._debounceTimer = null;\n /** @type {number} current highlighted index */\n this._activeIndex = -1;\n /** @type {Array<{id, label, avatar?}>} */\n this._items = [];\n /** @type {boolean} */\n this._open = false;\n /** Position of trigger character in the text node */\n this._triggerNode = null;\n this._triggerOffset = 0;\n /** @type {DOMRect|null} Caret rect captured synchronously during input event */\n this._caretRect = null;\n\n this._disposers = [];\n }\n\n initialize() {\n const cfg = this.context.options.mention;\n if (!cfg || typeof cfg.onSearch !== 'function') return this;\n this._cfg = {\n trigger: cfg.trigger || '@',\n minChars: cfg.minChars ?? 0,\n maxResults: cfg.maxResults ?? 8,\n debounce: cfg.debounce ?? 200,\n onSearch: cfg.onSearch,\n onInsert: cfg.onInsert || null,\n mentionClass: cfg.mentionClass || 'an-mention',\n allowSpaces: cfg.allowSpaces || false,\n };\n\n this._buildDropdown();\n\n const editable = this.context.layoutInfo.editable;\n const d1 = on(editable, 'keydown', (e) => this._onKeydown(e));\n const d2 = on(editable, 'input', () => this._onInput());\n const d3 = on(document, 'click', (e) => this._onDocClick(e));\n this._disposers.push(d1, d2, d3);\n return this;\n }\n\n destroy() {\n clearTimeout(this._debounceTimer);\n if (this._dropdown && this._dropdown.parentNode) {\n this._dropdown.parentNode.removeChild(this._dropdown);\n }\n this._dropdown = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Dropdown DOM\n // ---------------------------------------------------------------------------\n\n _buildDropdown() {\n const el = document.createElement('div');\n el.className = 'an-mention-dropdown';\n el.setAttribute('role', 'listbox');\n document.body.appendChild(el);\n this._dropdown = el;\n }\n\n _renderItems(items) {\n const dd = this._dropdown;\n dd.innerHTML = '';\n this._items = items.slice(0, this._cfg.maxResults);\n this._activeIndex = this._items.length > 0 ? 0 : -1;\n\n this._items.forEach((item, i) => {\n const li = document.createElement('div');\n li.className = 'an-mention-item';\n li.setAttribute('role', 'option');\n li.dataset.index = i;\n if (item.avatar) {\n const img = document.createElement('img');\n img.src = item.avatar;\n img.className = 'an-mention-avatar';\n img.alt = '';\n li.appendChild(img);\n }\n const label = document.createElement('span');\n label.textContent = item.label;\n li.appendChild(label);\n li.addEventListener('mousedown', (e) => e.preventDefault());\n li.addEventListener('click', () => this._select(i));\n dd.appendChild(li);\n });\n\n this._highlightItem(this._activeIndex);\n }\n\n _highlightItem(index) {\n if (!this._dropdown) return;\n this._dropdown.querySelectorAll('.an-mention-item').forEach((el, i) => {\n el.classList.toggle('an-mention-active', i === index);\n });\n this._activeIndex = index;\n }\n\n _positionDropdown() {\n const dd = this._dropdown;\n const rect = this._caretRect;\n if (!rect || rect.height === 0) return;\n\n // Measure while invisible to avoid layout flash\n dd.style.visibility = 'hidden';\n dd.style.display = 'block';\n\n const ddh = dd.offsetHeight;\n const ddw = dd.offsetWidth;\n\n // position:fixed — coords are already viewport-relative, no scroll offset needed\n let top = rect.bottom + 4;\n let left = rect.left;\n\n if (rect.bottom + ddh + 8 > window.innerHeight) {\n top = rect.top - ddh - 4;\n }\n left = Math.max(8, Math.min(left, window.innerWidth - ddw - 8));\n\n dd.style.top = `${top}px`;\n dd.style.left = `${left}px`;\n dd.style.visibility = '';\n }\n\n _showDropdown() {\n this._open = true;\n this._positionDropdown();\n }\n\n _hideDropdown() {\n if (this._dropdown) this._dropdown.style.display = 'none';\n this._open = false;\n this._items = [];\n this._activeIndex = -1;\n this._triggerNode = null;\n this._caretRect = null;\n this._query = '';\n }\n\n /**\n * Captures the caret rect synchronously during the input event.\n * Must be called while the DOM event is still live — getClientRects() on a\n * collapsed range is reliable at this point but often empty inside async callbacks.\n */\n _captureCaretRect() {\n // Prefer a range over the trigger character — it has non-zero width and\n // getBoundingClientRect() reliably returns a valid rect.\n if (this._triggerNode && this._triggerNode.isConnected) {\n try {\n const r = document.createRange();\n const end = Math.min(this._triggerOffset + 1, this._triggerNode.textContent.length);\n r.setStart(this._triggerNode, this._triggerOffset);\n r.setEnd(this._triggerNode, end);\n const candidate = r.getBoundingClientRect();\n if (candidate.height > 0) {\n this._caretRect = candidate;\n return;\n }\n } catch (_) {}\n }\n\n // Fallback: use getClientRects() on the current collapsed selection\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const rects = sel.getRangeAt(0).getClientRects();\n if (rects.length > 0) {\n this._caretRect = rects[rects.length - 1];\n }\n }\n\n // ---------------------------------------------------------------------------\n // Query detection\n // ---------------------------------------------------------------------------\n\n _getQueryAtCursor() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n if (!range.collapsed) return null;\n\n const node = range.startContainer;\n if (node.nodeType !== Node.TEXT_NODE) return null;\n\n const text = node.textContent.slice(0, range.startOffset);\n const trigger = this._cfg.trigger;\n\n // Find the last occurrence of trigger in the text before cursor\n const triggerIdx = text.lastIndexOf(trigger);\n if (triggerIdx === -1) return null;\n\n const afterTrigger = text.slice(triggerIdx + trigger.length);\n\n // No spaces allowed unless configured\n if (!this._cfg.allowSpaces && /\\s/.test(afterTrigger)) return null;\n\n if (afterTrigger.length < this._cfg.minChars) return null;\n\n this._triggerNode = node;\n this._triggerOffset = triggerIdx;\n return afterTrigger;\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n _onInput() {\n if (!this._cfg) return;\n const query = this._getQueryAtCursor();\n if (query === null) {\n this._hideDropdown();\n return;\n }\n\n // Capture caret rect NOW, synchronously while the input event is live.\n // Inside a setTimeout/debounce callback the selection may still be valid\n // but getClientRects() on a collapsed range often returns empty in that context.\n this._captureCaretRect();\n\n this._query = query;\n clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._cfg.onSearch(this._query, (items) => {\n if (!Array.isArray(items) || items.length === 0) {\n this._hideDropdown();\n return;\n }\n this._renderItems(items);\n this._showDropdown();\n });\n }, this._cfg.debounce);\n }\n\n _onKeydown(e) {\n if (!this._cfg || !this._open) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n const next = (this._activeIndex + 1) % this._items.length;\n this._highlightItem(next);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n const prev = (this._activeIndex - 1 + this._items.length) % this._items.length;\n this._highlightItem(prev);\n } else if (e.key === 'Enter' || e.key === 'Tab') {\n if (this._activeIndex >= 0) {\n e.preventDefault();\n this._select(this._activeIndex);\n }\n } else if (e.key === 'Escape') {\n this._hideDropdown();\n }\n }\n\n _onDocClick(e) {\n if (!this._open) return;\n if (this._dropdown && this._dropdown.contains(e.target)) return;\n this._hideDropdown();\n }\n\n // ---------------------------------------------------------------------------\n // Insert\n // ---------------------------------------------------------------------------\n\n _select(index) {\n const item = this._items[index];\n if (!item) return;\n\n // Delete the trigger + query text from the DOM\n if (this._triggerNode) {\n const node = this._triggerNode;\n const before = node.textContent.slice(0, this._triggerOffset);\n const after = node.textContent.slice(this._triggerOffset + this._cfg.trigger.length + this._query.length);\n node.textContent = before + after;\n\n // Move cursor to where the trigger was\n const sel = window.getSelection();\n const range = document.createRange();\n range.setStart(node, this._triggerOffset);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n // Build the chip HTML\n let html;\n if (typeof this._cfg.onInsert === 'function') {\n html = this._cfg.onInsert(item);\n }\n if (!html) {\n const cls = this._cfg.mentionClass;\n html = `<span class=\"${cls}\" data-mention-id=\"${item.id}\" contenteditable=\"false\">@${item.label}</span>`;\n }\n\n // Insert a trailing space so the cursor lands outside the chip\n this.context.invoke('editor.insertHTML', html + '​');\n this._hideDropdown();\n this.context.triggerEvent('change', this.context.getHTML());\n }\n}\n","/**\n * Context.js - Central hub for the editor instance\n * Holds references to all sub-modules and manages inter-module communication.\n * Inspired by Summernote's Context.js\n */\n\nimport { mergeDeep } from './core/func.js';\nimport { defaultOptions } from './settings.js';\nimport { resolveLocale } from './i18n/index.js';\nimport { renderLayout } from './renderer.js';\nimport { on } from './core/dom.js';\n\n// Modules\nimport { Editor } from './module/Editor.js';\nimport { Toolbar } from './module/Toolbar.js';\nimport { Statusbar } from './module/Statusbar.js';\nimport { Clipboard } from './module/Clipboard.js';\nimport { Placeholder } from './module/Placeholder.js';\nimport { Codeview } from './module/Codeview.js';\nimport { Fullscreen } from './module/Fullscreen.js';\nimport { LinkDialog } from './module/LinkDialog.js';\nimport { ImageDialog } from './module/ImageDialog.js';\nimport { VideoDialog } from './module/VideoDialog.js';\nimport { ImageResizer } from './module/ImageResizer.js';\nimport { VideoResizer } from './module/VideoResizer.js';\nimport { LinkTooltip } from './module/LinkTooltip.js';\nimport { ImageTooltip } from './module/ImageTooltip.js';\nimport { VideoTooltip } from './module/VideoTooltip.js';\nimport { TableTooltip } from './module/TableTooltip.js';\nimport { CodeTooltip } from './module/CodeTooltip.js';\nimport { EmojiDialog } from './module/EmojiDialog.js';\nimport { IconDialog } from './module/IconDialog.js';\nimport { ContextMenu } from './module/ContextMenu.js';\nimport { ShortcutsDialog } from './module/ShortcutsDialog.js';\nimport { FindReplace } from './module/FindReplace.js';\nimport { ImageCropOverlay } from './module/ImageCropOverlay.js';\nimport { AutoSaveRestore } from './module/AutoSaveRestore.js';\nimport { MarkdownShortcuts } from './module/MarkdownShortcuts.js';\nimport { BubbleToolbar } from './module/BubbleToolbar.js';\nimport { Mention } from './module/Mention.js';\n\n/** Module registry shared across all Context instances (populated via AutumnNote.registerModule). */\nexport const _customModules = new Map();\n\nexport class Context {\n /**\n * @param {HTMLElement} targetEl - The element to replace with the editor\n * @param {import('./settings.js').AsnOptions} [userOptions]\n */\n constructor(targetEl, userOptions = {}) {\n this.targetEl = targetEl;\n this.options = mergeDeep(defaultOptions, userOptions);\n\n /** @type {import('./i18n/index.js').AsnLocale} */\n this.locale = resolveLocale(this.options.lang);\n\n /** @type {{ container: HTMLElement, editable: HTMLElement, toolbar?: HTMLElement, statusbar?: HTMLElement }} */\n this.layoutInfo = {};\n\n /** @type {Map<string, Function[]>} */\n this._listeners = new Map();\n\n /** @type {Map<string, object>} */\n this._modules = new Map();\n\n this._disposers = [];\n this._alive = false;\n }\n\n // ---------------------------------------------------------------------------\n // Initialisation\n // ---------------------------------------------------------------------------\n\n initialize() {\n // 1. Render the DOM skeleton\n const { container, editable } = renderLayout(this.targetEl, this.options);\n this.layoutInfo.container = container;\n this.layoutInfo.editable = editable;\n\n // 2. Register core modules\n this._registerModules();\n\n // 3. Attach toolbar/statusbar to container\n const toolbar = this._modules.get('toolbar');\n if (toolbar && toolbar.el) {\n container.insertBefore(toolbar.el, editable);\n this.layoutInfo.toolbar = toolbar.el;\n }\n\n const statusbar = this._modules.get('statusbar');\n if (statusbar && statusbar.el) {\n container.appendChild(statusbar.el);\n this.layoutInfo.statusbar = statusbar.el;\n }\n\n // 4. Bind editor-level events\n this._bindEditorEvents(editable);\n\n // 5. Auto-focus if requested\n if (this.options.focus) {\n editable.focus();\n }\n\n this._alive = true;\n\n // Initial toolbar sync so dropdowns show the correct font on load\n this.invoke('toolbar.refresh');\n\n if (typeof this.options.onInit === 'function') {\n this.options.onInit(this);\n }\n\n return this;\n }\n\n _registerModules() {\n const register = (name, ModuleClass) => {\n const instance = new ModuleClass(this);\n this._modules.set(name, instance);\n instance.initialize();\n };\n\n register('editor', Editor);\n register('toolbar', Toolbar);\n register('statusbar', Statusbar);\n register('clipboard', Clipboard);\n register('contextMenu', ContextMenu);\n register('placeholder', Placeholder);\n register('codeview', Codeview);\n register('fullscreen', Fullscreen);\n register('linkDialog', LinkDialog);\n register('imageDialog', ImageDialog);\n register('videoDialog', VideoDialog);\n register('imageResizer', ImageResizer);\n register('videoResizer', VideoResizer);\n register('linkTooltip', LinkTooltip);\n register('imageTooltip', ImageTooltip);\n register('videoTooltip', VideoTooltip);\n register('tableTooltip', TableTooltip);\n register('codeTooltip', CodeTooltip);\n register('emojiDialog', EmojiDialog);\n register('iconDialog', IconDialog);\n register('shortcutsDialog', ShortcutsDialog);\n register('findReplace', FindReplace);\n register('imageCropOverlay', ImageCropOverlay);\n register('autoSaveRestore', AutoSaveRestore);\n register('markdownShortcuts', MarkdownShortcuts);\n register('bubbleToolbar', BubbleToolbar);\n register('mention', Mention);\n\n // Custom modules registered via AutumnNote.registerModule()\n for (const [name, ModuleClass] of _customModules) {\n register(name, ModuleClass);\n }\n }\n\n /**\n * Registers and initialises a custom module on this instance.\n * @param {string} name\n * @param {Function} ModuleClass\n * @returns {this}\n */\n registerModule(name, ModuleClass) {\n if (this._modules.has(name)) return this;\n const instance = new ModuleClass(this);\n instance.initialize();\n this._modules.set(name, instance);\n return this;\n }\n\n _bindEditorEvents(editable) {\n // Keep the original textarea/input value in sync immediately on every input.\n // This guarantees form.submit() sees fresh data even before debounced change.\n const d0 = on(editable, 'input', () => this._syncToTarget());\n const d1 = on(editable, 'focus', () => {\n this.layoutInfo.container.classList.add('an-focused');\n if (typeof this.options.onFocus === 'function') {\n this.options.onFocus(this);\n }\n });\n const d2 = on(editable, 'blur', () => {\n this.layoutInfo.container.classList.remove('an-focused');\n this._syncToTarget();\n if (typeof this.options.onBlur === 'function') {\n this.options.onBlur(this);\n }\n });\n // Sync textarea/input value on every change so form.submit() always gets fresh content\n const d3 = this.on('change', () => this._syncToTarget());\n this._disposers.push(d0, d1, d2, d3);\n\n // Auto-save to localStorage on every change (also writes :asrmeta for restore banner)\n if (this.options.autoSave && this.options.autoSaveKey) {\n const d4 = this.on('change', () => {\n try {\n const key = this.options.autoSaveKey;\n localStorage.setItem(key, this.getHTML());\n localStorage.setItem(key + ':asrmeta', JSON.stringify({ savedAt: Date.now() }));\n } catch (_) {}\n });\n this._disposers.push(d4);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Module invocation\n // ---------------------------------------------------------------------------\n\n /**\n * Invokes a method on a registered module.\n * Format: 'moduleName.methodName'\n * @param {string} path - e.g. 'editor.bold'\n * @param {...*} args\n * @returns {*}\n */\n invoke(path, ...args) {\n const [moduleName, methodName] = path.split('.');\n const module = this._modules.get(moduleName);\n if (!module) {\n console.warn(`[AutumnNote] invoke: module \"${moduleName}\" not found (path: \"${path}\")`);\n return undefined;\n }\n if (typeof module[methodName] !== 'function') {\n console.warn(`[AutumnNote] invoke: method \"${methodName}\" not found on module \"${moduleName}\" (path: \"${path}\")`);\n return undefined;\n }\n return module[methodName](...args);\n }\n\n // ---------------------------------------------------------------------------\n // Event system\n // ---------------------------------------------------------------------------\n\n /**\n * Subscribes to an editor event.\n * @param {string} eventName\n * @param {Function} handler\n * @returns {() => void} unsubscribe\n */\n on(eventName, handler) {\n if (!this._listeners.has(eventName)) {\n this._listeners.set(eventName, []);\n }\n this._listeners.get(eventName).push(handler);\n return () => this.off(eventName, handler);\n }\n\n /**\n * Unsubscribes from an editor event.\n * @param {string} eventName\n * @param {Function} handler\n */\n off(eventName, handler) {\n const handlers = this._listeners.get(eventName);\n if (!handlers) return;\n const idx = handlers.indexOf(handler);\n if (idx !== -1) handlers.splice(idx, 1);\n }\n\n /**\n * Triggers an editor event.\n * @param {string} eventName\n * @param {...*} args\n */\n triggerEvent(eventName, ...args) {\n const handlers = this._listeners.get(eventName) || [];\n handlers.forEach((h) => h(...args));\n\n // Also call options callback if present (e.g. onChange)\n const cbName = 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1);\n if (typeof this.options[cbName] === 'function') {\n this.options[cbName](...args);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public editor API\n // ---------------------------------------------------------------------------\n\n /**\n * Returns the current HTML content of the editor.\n * @returns {string}\n */\n getHTML() {\n return this.invoke('editor.getHTML');\n }\n\n /**\n * Sets the HTML content of the editor.\n * @param {string} html\n */\n setHTML(html) {\n this.invoke('editor.setHTML', html);\n }\n\n /**\n * Returns the plain text content of the editor.\n * @returns {string}\n */\n getText() {\n return this.invoke('editor.getText');\n }\n\n /**\n * Sets the editor content as plain text (HTML-escaped).\n * @param {string} text\n */\n setText(text) {\n this.invoke('editor.setText', text);\n }\n\n /**\n * Clears the editor content.\n */\n clear() {\n this.invoke('editor.clear');\n }\n\n /**\n * Resets the undo/redo history stack.\n * Useful after programmatically loading a new document via setHTML() / setMarkdown()\n * so that Ctrl+Z cannot undo back to the previous document.\n */\n clearHistory() {\n this.invoke('editor.clearHistory');\n }\n\n /**\n * Returns true when the editor has no meaningful content.\n * @returns {boolean}\n */\n isEmpty() {\n return this.invoke('editor.isEmpty');\n }\n\n /**\n * Inserts HTML at the current cursor position.\n * @param {string} html\n */\n insertHTML(html) {\n this.invoke('editor.insertHTML', html);\n }\n\n /**\n * Inserts plain text at the current cursor position.\n * @param {string} text\n */\n insertText(text) {\n this.invoke('editor.insertText', text);\n }\n\n /**\n * Sets editor content from a Markdown string.\n * @param {string} md\n */\n setMarkdown(md) {\n this.invoke('editor.setMarkdown', md);\n }\n\n /**\n * Returns the editor content as Markdown.\n * @returns {string}\n */\n getMarkdown() {\n return this.invoke('editor.getMarkdown');\n }\n\n /**\n * Returns the current word count of the editor content.\n * @returns {number}\n */\n getWordCount() {\n return this.invoke('statusbar.getWordCount') ?? 0;\n }\n\n /**\n * Returns the current character count of the editor content.\n * @returns {number}\n */\n getCharCount() {\n return this.invoke('statusbar.getCharCount') ?? 0;\n }\n\n /**\n * Downloads the editor content as an HTML file.\n * @param {string} [filename='document.html']\n */\n downloadHTML(filename = 'document.html') {\n this._download(this.getHTML(), filename, 'text/html');\n }\n\n /**\n * Downloads the editor content as a plain-text file.\n * @param {string} [filename='document.txt']\n */\n downloadText(filename = 'document.txt') {\n this._download(this.getText(), filename, 'text/plain');\n }\n\n /**\n * Downloads the editor content as a Markdown file.\n * @param {string} [filename='document.md']\n */\n downloadMarkdown(filename = 'document.md') {\n this._download(this.getMarkdown(), filename, 'text/markdown');\n }\n\n /**\n * Creates a temporary Blob URL and triggers a browser file download.\n * @param {string} content\n * @param {string} filename\n * @param {string} mimeType\n */\n _download(content, filename, mimeType) {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }\n\n /**\n * Opens the editor content in a new window and triggers the browser print dialog.\n * @param {string} [title='']\n */\n print(title = '') {\n const content = this.getHTML();\n const safeTitle = (title || '').replace(/</g, '<').replace(/>/g, '>');\n const w = window.open('', '_blank');\n if (!w) return; // popup blocked by browser\n w.document.write(\n '<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\">' +\n `<title>${safeTitle}</title>` +\n '<style>' +\n 'body{font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,Arial,sans-serif;font-size:14px;line-height:1.6;padding:20mm;color:#111827;}' +\n 'ul.an-checklist{list-style:none;padding-left:0;}' +\n 'ul.an-checklist li{padding-left:24px;position:relative;margin:2px 0;}' +\n 'ul.an-checklist li input[type=\"checkbox\"]{position:absolute;left:0;top:3px;}' +\n 'code{background:#f3f4f6;border-radius:3px;padding:.1em .35em;font-family:monospace;}' +\n 'pre{background:#f3f4f6;padding:.75em 1em;border-radius:4px;overflow-x:auto;}' +\n 'table{border-collapse:collapse;}td,th{border:1px solid #d1d5db;padding:4px 8px;}' +\n '</style>' +\n `</head><body>${content}</body></html>`,\n );\n w.document.close();\n w.onload = () => { w.print(); };\n }\n\n /**\n * Sets whether the editor is disabled (readonly).\n * @param {boolean} disabled\n */\n setDisabled(disabled) {\n const editable = this.layoutInfo.editable;\n if (disabled) {\n editable.setAttribute('contenteditable', 'false');\n this.layoutInfo.container.classList.add('an-disabled');\n editable.querySelectorAll('ul.an-checklist input[type=\"checkbox\"]').forEach((cb) => {\n cb.setAttribute('disabled', '');\n });\n } else {\n editable.setAttribute('contenteditable', 'true');\n this.layoutInfo.container.classList.remove('an-disabled');\n editable.querySelectorAll('ul.an-checklist input[type=\"checkbox\"]').forEach((cb) => {\n cb.removeAttribute('disabled');\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // Destroy\n // ---------------------------------------------------------------------------\n\n /**\n * Completely removes the editor and restores the original element.\n */\n destroy() {\n if (!this._alive) return;\n\n this._modules.forEach((module) => {\n if (typeof module.destroy === 'function') module.destroy();\n });\n this._modules.clear();\n\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n const container = this.layoutInfo.container;\n if (container && container.parentNode) {\n // Restore original element\n this.targetEl.style.display = '';\n container.parentNode.removeChild(container);\n }\n\n if (typeof this.options.onDestroy === 'function') {\n this.options.onDestroy(this);\n }\n\n this._alive = false;\n this._listeners.clear();\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Syncs editor HTML back into the original textarea/input for form submission.\n */\n _syncToTarget() {\n if (this.targetEl.tagName === 'TEXTAREA' || this.targetEl.tagName === 'INPUT') {\n this.targetEl.value = this.getHTML();\n }\n }\n}\n","/**\n * lists.js - Array/list utility helpers\n * Inspired by Summernote's lists.js\n */\n\n/**\n * Returns the last element of an array.\n * @template T\n * @param {T[]} arr\n * @returns {T|undefined}\n */\nexport function last(arr) {\n return arr[arr.length - 1];\n}\n\n/**\n * Returns the first element of an array.\n * @template T\n * @param {T[]} arr\n * @returns {T|undefined}\n */\nexport function first(arr) {\n return arr[0];\n}\n\n/**\n * Returns a new array without the last n items.\n * @template T\n * @param {T[]} arr\n * @param {number} [n=1]\n * @returns {T[]}\n */\nexport function initial(arr, n = 1) {\n return arr.slice(0, arr.length - n);\n}\n\n/**\n * Returns a new array without the first n items.\n * @template T\n * @param {T[]} arr\n * @param {number} [n=1]\n * @returns {T[]}\n */\nexport function tail(arr, n = 1) {\n return arr.slice(n);\n}\n\n/**\n * Returns a flattened (one level) array.\n * @template T\n * @param {T[][]} arr\n * @returns {T[]}\n */\nexport function flatten(arr) {\n return arr.reduce((acc, val) => acc.concat(val), []);\n}\n\n/**\n * Returns unique elements of an array (using Set).\n * @template T\n * @param {T[]} arr\n * @returns {T[]}\n */\nexport function unique(arr) {\n return [...new Set(arr)];\n}\n\n/**\n * Splits an array into chunks of size n.\n * @template T\n * @param {T[]} arr\n * @param {number} n\n * @returns {T[][]}\n */\nexport function chunk(arr, n) {\n const result = [];\n for (let i = 0; i < arr.length; i += n) {\n result.push(arr.slice(i, i + n));\n }\n return result;\n}\n\n/**\n * Groups array elements by a key function.\n * @template T\n * @param {T[]} arr\n * @param {(item: T) => string} keyFn\n * @returns {Record<string, T[]>}\n */\nexport function groupBy(arr, keyFn) {\n return arr.reduce((groups, item) => {\n const key = keyFn(item);\n if (!groups[key]) {\n groups[key] = [];\n }\n groups[key].push(item);\n return groups;\n }, {});\n}\n\n/**\n * Returns true if all elements satisfy the predicate.\n * @template T\n * @param {T[]} arr\n * @param {(item: T) => boolean} predicate\n * @returns {boolean}\n */\nexport function all(arr, predicate) {\n return arr.every(predicate);\n}\n\n/**\n * Returns true if any element satisfies the predicate.\n * @template T\n * @param {T[]} arr\n * @param {(item: T) => boolean} predicate\n * @returns {boolean}\n */\nexport function any(arr, predicate) {\n return arr.some(predicate);\n}\n","/**\n * env.js - Environment / browser detection\n * Inspired by Summernote's env.js\n */\n\nconst userAgent = navigator.userAgent;\n\nexport const env = {\n /** True if browser is Chrome */\n isChrome: /Chrome\\//.test(userAgent),\n /** True if browser is Firefox */\n isFF: /Firefox\\//.test(userAgent),\n /** True if browser is Safari (not Chrome) */\n isSafari: /^((?!chrome|android).)*safari/i.test(userAgent),\n /** True if browser is Edge (Chromium) */\n isEdge: /Edg\\//.test(userAgent),\n /** True if running on macOS */\n isMac: /Macintosh/.test(userAgent),\n /** True if running on mobile */\n isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent),\n /** True if touch is supported */\n isTouch: 'ontouchstart' in window || navigator.maxTouchPoints > 0,\n /** Modifier key name depending on platform */\n modifierKey: /Macintosh/.test(userAgent) ? 'metaKey' : 'ctrlKey',\n};\n","/**\n * index.js - Public entry point for AutumnNote\n *\n * Usage (module):\n * import AutumnNote from 'autumnnote';\n * const editor = AutumnNote.create('#my-editor', { placeholder: 'Start typing…' });\n *\n * Usage (UMD / script tag):\n * const editor = AutumnNote.create('#my-editor');\n */\n\nimport '../styles/autumnnote.scss';\nimport { Context, _customModules } from './Context.js';\nimport { defaultOptions } from './settings.js';\n\n// Snapshot of factory defaults taken at module-load time (before any setDefaults() calls)\nconst _originalDefaults = { ...defaultOptions };\n\n// Re-export for tree-shaking / module consumers\nexport { Context } from './Context.js';\nexport { defaultOptions } from './settings.js';\nexport * from './core/dom.js';\nexport * from './core/range.js';\nexport * from './core/func.js';\nexport * from './core/key.js';\nexport * from './core/lists.js';\nexport * from './core/env.js';\nexport * from './core/sanitise.js';\nexport * from './module/Buttons.js';\nexport { locales, resolveLocale } from './i18n/index.js';\n\n// ---------------------------------------------------------------------------\n// Main factory\n// ---------------------------------------------------------------------------\n\n/** @type {WeakMap<Element, Context>} */\nconst instances = new WeakMap();\n\nconst AutumnNote = {\n /**\n * Creates (or returns existing) editor instance on one or more elements.\n *\n * @param {string|Element|NodeList|Element[]} selector\n * @param {import('./settings.js').AsnOptions} [options]\n * @returns {Context|Context[]} single Context or array of Contexts\n */\n create(selector, options = {}) {\n const elements = resolveElements(selector);\n const ctxs = elements.map((el) => {\n if (instances.has(el)) return instances.get(el);\n const ctx = new Context(el, options);\n ctx.initialize();\n instances.set(el, ctx);\n return ctx;\n });\n return ctxs.length === 1 ? ctxs[0] : ctxs;\n },\n\n /**\n * Destroys the editor(s) on the given selector.\n * @param {string|Element|NodeList|Element[]} selector\n */\n destroy(selector) {\n resolveElements(selector).forEach((el) => {\n const ctx = instances.get(el);\n if (ctx) {\n ctx.destroy();\n instances.delete(el);\n }\n });\n },\n\n /**\n * Returns the Context instance for a given element (or null).\n * @param {string|Element} selector\n * @returns {Context|null}\n */\n getInstance(selector) {\n const el = typeof selector === 'string' ? document.querySelector(selector) : selector;\n return el ? instances.get(el) || null : null;\n },\n\n /** Returns a shallow copy of the default options (read-only snapshot). */\n get defaults() { return { ...defaultOptions }; },\n\n /** Merges properties into the global defaults, applied to all future instances. */\n setDefaults(overrides) { Object.assign(defaultOptions, overrides); },\n\n /** Restores global defaults to their original factory values. */\n resetDefaults() {\n Object.keys(defaultOptions).forEach((k) => delete defaultOptions[k]);\n Object.assign(defaultOptions, _originalDefaults);\n },\n\n /**\n * Registers a custom module to be included in every new editor instance.\n * @param {string} name - unique module key used for ctx.invoke() calls\n * @param {Function} ModuleClass - class with initialize() and optional destroy()\n */\n registerModule(name, ModuleClass) { _customModules.set(name, ModuleClass); },\n\n /** Library version */\n version: '1.1.1',\n};\n\n// ---------------------------------------------------------------------------\n// Helper\n// ---------------------------------------------------------------------------\n\n/**\n * @param {string|Element|NodeList|Element[]} selector\n * @returns {Element[]}\n */\nfunction resolveElements(selector) {\n if (typeof selector === 'string') {\n return Array.from(document.querySelectorAll(selector));\n }\n if (selector instanceof Element) {\n return [selector];\n }\n if (selector instanceof NodeList || Array.isArray(selector)) {\n return Array.from(selector);\n }\n return [];\n}\n\nexport default AutumnNote;\n"],"mappings":"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C;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CAGnD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAK;EAAkC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAiC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAK;EAAkC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAO;EAAiC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAiC;EAAS;CACjD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAClD;EAAC;EAAM;EAAkC;EAAS;CAGlD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CAGnD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAK;EAAkC;EAAO;CAC/C;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM;EAAkC;EAAO;CAChD;EAAC;EAAM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AAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAK;EAAkC;EAAU;CAClD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAK;EAAkC;EAAU;CAClD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EAAU;CACnD;EAAC;EAAM;EAAkC;EA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"}
|