autumnnote 2.0.0 → 2.2.0

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.
Files changed (64) hide show
  1. package/README.md +72 -5
  2. package/dist/autumnnote.cjs +20 -20
  3. package/dist/autumnnote.css +1 -1
  4. package/dist/autumnnote.es.js +661 -798
  5. package/dist/autumnnote.es.js.map +1 -1
  6. package/dist/autumnnote.min.js +20 -20
  7. package/dist/autumnnote.umd.js +20 -20
  8. package/dist/autumnnote.umd.js.map +1 -1
  9. package/dist/icon-data-V0Xqv-wX.js +255 -0
  10. package/dist/icon-data-V0Xqv-wX.js.map +1 -0
  11. package/package.json +13 -4
  12. package/types/index.d.ts +8 -0
  13. package/src/js/Context.js +0 -854
  14. package/src/js/core/detectLang.js +0 -98
  15. package/src/js/core/dom.js +0 -372
  16. package/src/js/core/env.js +0 -25
  17. package/src/js/core/key.js +0 -66
  18. package/src/js/core/lists.js +0 -121
  19. package/src/js/core/markdown.js +0 -695
  20. package/src/js/core/range.js +0 -194
  21. package/src/js/core/sanitise.js +0 -231
  22. package/src/js/editing/History.js +0 -266
  23. package/src/js/editing/Style.js +0 -812
  24. package/src/js/editing/Table.js +0 -105
  25. package/src/js/editing/Typing.js +0 -397
  26. package/src/js/index.js +0 -193
  27. package/src/js/index.umd.js +0 -17
  28. package/src/js/module/AutoSaveRestore.js +0 -125
  29. package/src/js/module/BaseDialog.js +0 -133
  30. package/src/js/module/BaseMediaTooltip.js +0 -142
  31. package/src/js/module/BaseResizer.js +0 -312
  32. package/src/js/module/BubbleToolbar.js +0 -483
  33. package/src/js/module/Buttons.js +0 -399
  34. package/src/js/module/Clipboard.js +0 -579
  35. package/src/js/module/CodeTooltip.js +0 -493
  36. package/src/js/module/Codeview.js +0 -125
  37. package/src/js/module/ContextMenu.js +0 -621
  38. package/src/js/module/Editor.js +0 -747
  39. package/src/js/module/EmojiDialog.js +0 -254
  40. package/src/js/module/FindReplace.js +0 -512
  41. package/src/js/module/Fullscreen.js +0 -80
  42. package/src/js/module/IconDialog.js +0 -618
  43. package/src/js/module/ImageCropOverlay.js +0 -586
  44. package/src/js/module/ImageDialog.js +0 -193
  45. package/src/js/module/ImageResizer.js +0 -42
  46. package/src/js/module/ImageTooltip.js +0 -285
  47. package/src/js/module/LinkDialog.js +0 -145
  48. package/src/js/module/LinkTooltip.js +0 -250
  49. package/src/js/module/MarkdownShortcuts.js +0 -250
  50. package/src/js/module/Mention.js +0 -365
  51. package/src/js/module/Placeholder.js +0 -51
  52. package/src/js/module/ShortcutsDialog.js +0 -111
  53. package/src/js/module/SlashMenu.js +0 -376
  54. package/src/js/module/Statusbar.js +0 -246
  55. package/src/js/module/TableTooltip.js +0 -1521
  56. package/src/js/module/Toolbar.js +0 -750
  57. package/src/js/module/VideoDialog.js +0 -193
  58. package/src/js/module/VideoResizer.js +0 -66
  59. package/src/js/module/VideoTooltip.js +0 -248
  60. package/src/js/module/emoji-data.js +0 -496
  61. package/src/js/renderer.js +0 -120
  62. package/src/js/settings.js +0 -214
  63. package/src/styles/_variables.scss +0 -48
  64. package/src/styles/autumnnote.scss +0 -2866
@@ -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","_S","ICON_SVG","ICON_SVG","ICON_SVG","ICONS","SHOW_DELAY","HIDE_DELAY","SHOW_DELAY","HIDE_DELAY","ICONS","ICONS","SHOW_DELAY","HIDE_DELAY","ICONS","ICONS","COLOR_PRESETS","clamp","outW","outH"],"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/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/core/detectLang.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/BaseDialog.js","../src/js/module/LinkDialog.js","../src/js/module/ImageDialog.js","../src/js/module/VideoDialog.js","../src/js/module/BaseResizer.js","../src/js/module/ImageResizer.js","../src/js/module/VideoResizer.js","../src/js/module/LinkTooltip.js","../src/js/module/BaseMediaTooltip.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/module/SlashMenu.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 * Create a wrapper that limits how often `fn` can be invoked while ensuring the last call in a burst is executed.\n * @param {Function} fn - Function to be throttled.\n * @param {number} limit - Time globalThis in milliseconds during which at most one call is allowed.\n * @returns {Function} A wrapper function that invokes `fn` at most once per `limit` milliseconds; calls preserve `this` and original arguments and schedule a trailing invocation for the final call in a burst.\n */\nexport function throttle(fn, limit) {\n let lastCall = -Infinity;\n let trailingTimer = null;\n return function (...args) {\n const now = performance.now();\n const elapsed = now - lastCall;\n if (elapsed >= limit) {\n lastCall = now;\n clearTimeout(trailingTimer);\n trailingTimer = null;\n return fn.apply(this, args);\n }\n // Ensure the final event in a burst is not dropped\n clearTimeout(trailingTimer);\n trailingTimer = setTimeout(() => {\n lastCall = performance.now();\n trailingTimer = null;\n fn.apply(this, args);\n }, limit - elapsed);\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: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n bottom: rect.bottom,\n right: 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?.nodeType === ELEMENT_NODE;\n/** @param {Node} node */\nexport const isText = (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) && /** @type {HTMLElement} */ (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 /** @type {Element|null} */ (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 /** @type {Element|null} */ (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?.parentNode) {\n /** @type {ChildNode} */ (node).remove();\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 /** @type {ChildNode} */ (node).remove();\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 * Determine whether a DOM node contains no visible content.\n *\n * Text nodes are considered empty when their `nodeValue` is empty. Void elements (e.g., `img`, `br`, `input`) are considered non-empty. An element with exactly one `<br>` child is treated as empty. For other elements, emptiness means trimmed `textContent` is empty and there are no descendant `img`, `video`, `hr`, or `table` elements.\n * @param {Node} node - Node to inspect for visible content.\n * @returns {boolean} `true` if the node has no visible content, `false` otherwise.\n */\nexport function isEmpty(node) {\n if (isText(node)) return !node.nodeValue;\n if (isVoid(node)) return false;\n if (node.childNodes.length === 1 && node.firstChild?.nodeName === 'BR') return true;\n return !node.textContent.trim() && !/** @type {Element} */ (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 = globalThis.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?.();\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.at(-1);\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n /** @type {HTMLElement} */ (last).focus();\n }\n } else if (document.activeElement === last) {\n e.preventDefault();\n /** @type {HTMLElement} */ (first).focus();\n }\n };\n\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n}\n\n/**\n * Makes a dialog box draggable by its handle element.\n * On first drag the box is pinned to its current viewport coordinates via\n * `position:fixed`, freeing it from the parent flex container's centering.\n * The position is clamped to the visible viewport.\n *\n * @param {HTMLElement} handle Element the user grabs (title bar / header)\n * @param {HTMLElement} box Element that actually moves\n * @returns {Function} Cleanup function (removes the mousedown listener)\n */\nexport function makeDraggable(handle, box) {\n handle.style.cursor = 'grab';\n\n const onMousedown = (e) => {\n if (e.button !== 0) return;\n // Don't start drag when clicking on interactive children of the handle\n if (/** @type {Element} */ (e.target).closest('button, input, select, textarea, a')) return;\n\n e.preventDefault();\n\n // First drag: snapshot position and pin to viewport with position:fixed\n if (!box.dataset.anDragPinned) {\n const r = box.getBoundingClientRect();\n box.style.position = 'fixed';\n box.style.margin = '0';\n box.style.left = `${r.left}px`;\n box.style.top = `${r.top}px`;\n box.dataset.anDragPinned = '1';\n }\n\n const startX = e.clientX - Number.parseFloat(box.style.left);\n const startY = e.clientY - Number.parseFloat(box.style.top);\n\n handle.style.cursor = 'grabbing';\n\n const onMove = (ev) => {\n const bw = box.offsetWidth;\n const bh = box.offsetHeight;\n box.style.left = `${Math.max(0, Math.min(ev.clientX - startX, globalThis.innerWidth - bw))}px`;\n box.style.top = `${Math.max(0, Math.min(ev.clientY - startY, globalThis.innerHeight - bh))}px`;\n };\n\n const onUp = () => {\n handle.style.cursor = 'grab';\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n };\n\n handle.addEventListener('mousedown', onMousedown);\n return () => handle.removeEventListener('mousedown', onMousedown);\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 void _e; // guard against detached nodes\n }\n return range;\n }\n\n /**\n * Select this wrapped range in the globalThis.\n */\n select() {\n const sel = globalThis.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 /** @type {Element|null} */ (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 /** @type {Element|null} */ (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 globalThis 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 = globalThis.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 = globalThis.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 = globalThis.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 = globalThis.getSelection();\n if (!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 = /** @type {Element|null} */ (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 uEl.remove();\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 = globalThis.getSelection();\n if (!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 = /** @type {Element|null} */ (sc)?.closest('s') || /** @type {Element|null} */ (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 sEl.remove();\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|Document} [editable] - scoping element to avoid touching nodes outside this editor\n */\nexport function fontSize(size, editable = document) {\n const sel = globalThis.getSelection();\n const wasCollapsed = !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?.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 (_) { void _; /* 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.remove();\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.at(-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 (_) { void _; /* 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 = globalThis.getSelection();\n if (sel?.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const checkLi = /** @type {Element|null} */ (container)?.closest('.an-checklist li');\n if (checkLi) {\n _checklistItemToP(/** @type {HTMLElement} */ (checkLi));\n return;\n }\n }\n execCommand('outdent');\n}\n\n/**\n * Convert a checklist <li> into a paragraph and move any following items into a new checklist.\n *\n * Preserves inline markup from the converted item, strips zero-width space anchors,\n * and replaces empty content with a non‑breaking space. If there are list items\n * after the converted item they are moved into a new <ul class=\"an-checklist\">\n * inserted immediately after the original list. The original <li> is removed and\n * the original list is removed if it becomes empty. Attempts to place the caret\n * at the start of the newly created <p>.\n * @param {HTMLElement} checkLi - The checklist `<li>` element to convert to a `<p>`.\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> preserving inline formatting (bold/italic/links) from the item's content\n const p = document.createElement('p');\n for (const child of checkLi.childNodes) {\n if (child.nodeType === 1 && /** @type {Element} */ (child).tagName === 'INPUT') continue;\n p.appendChild(child.cloneNode(true));\n }\n // Strip ZWS anchors left over from checklist markup\n p.innerHTML = p.innerHTML.replaceAll('\\u200B', '');\n if (!p.hasChildNodes() || !p.textContent.trim()) {\n p.innerHTML = '';\n p.appendChild(document.createTextNode('\\u00a0'));\n }\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 checkLi.remove();\n if (checkUl.children.length === 0) checkUl.remove();\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?.nodeType === 3 ? firstChild : p, 0);\n nr.collapse(true);\n const s = globalThis.getSelection();\n if (s) { s.removeAllRanges(); s.addRange(nr); }\n } catch {}\n}\n\n/**\n * Inserts an unordered (bulleted) list, or converts the current list to `<ul>`.\n *\n * When the cursor is already inside a list, direct DOM manipulation is used to\n * transition between list types — `execCommand` alone cannot handle checklist →\n * UL/OL conversions because it has no awareness of the `an-checklist` class or\n * the checkbox `<input>` elements.\n *\n * Transition paths:\n * - **Checklist → UL**: strips `an-checklist` class and all checkbox inputs;\n * converts `<ol>` container to `<ul>` via `changeTagName()` if needed.\n * - **OL → UL**: swaps the container tag via `changeTagName()`.\n * - **UL → paragraphs**: falls back to `execCommand('insertUnorderedList')`\n * which toggles the list off (browser-native behaviour).\n * - **No list → UL**: falls back to `execCommand('insertUnorderedList')`.\n */\n/**\n * Helper to get the closest ul/ol element containing the current selection.\n * @returns {Element|null}\n */\nfunction getSelectedList() {\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return null;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n return /** @type {Element|null} */ (container)?.closest('ul, ol') || null;\n}\n\n/**\n * Strips the checklist class and checkbox inputs from a list element.\n * @param {Element} listEl\n */\nfunction stripChecklist(listEl) {\n listEl.classList.remove('an-checklist');\n listEl.querySelectorAll('input[type=\"checkbox\"]').forEach(cb => cb.remove());\n}\n\nexport function insertUnorderedList() {\n const listEl = getSelectedList();\n if (listEl) {\n if (listEl.classList.contains('an-checklist')) {\n // Checklist → UL: strip checkboxes and class, swap tag if needed\n stripChecklist(listEl);\n if (listEl.tagName === 'OL') {\n changeTagName(listEl, 'ul');\n }\n } else if (listEl.tagName === 'OL') {\n // OL → UL: swap container tag\n changeTagName(listEl, 'ul');\n } else {\n // Already UL → toggle off via execCommand\n execCommand('insertUnorderedList');\n }\n } else {\n // Not in a list → create new UL via execCommand\n execCommand('insertUnorderedList');\n }\n}\n\n/**\n * Inserts an ordered (numbered) list, or converts the current list to `<ol>`.\n *\n * When the cursor is already inside a list, direct DOM manipulation is used to\n * transition between list types — `execCommand` alone cannot handle checklist →\n * UL/OL conversions because it has no awareness of the `an-checklist` class or\n * the checkbox `<input>` elements.\n *\n * Transition paths:\n * - **Checklist → OL**: strips `an-checklist` class and all checkbox inputs;\n * converts container to `<ol>` via `changeTagName()`.\n * - **UL → OL**: swaps the container tag via `changeTagName()`.\n * - **OL → paragraphs**: falls back to `execCommand('insertOrderedList')`\n * which toggles the list off (browser-native behaviour).\n * - **No list → OL**: falls back to `execCommand('insertOrderedList')`.\n */\nexport function insertOrderedList() {\n const listEl = getSelectedList();\n if (listEl) {\n if (listEl.classList.contains('an-checklist')) {\n // Checklist → OL: strip checkboxes and class, swap to <ol>\n stripChecklist(listEl);\n changeTagName(listEl, 'ol');\n } else if (listEl.tagName === 'UL') {\n // UL → OL: swap container tag\n changeTagName(listEl, 'ol');\n } else {\n // Already OL → toggle off via execCommand\n execCommand('insertOrderedList');\n }\n } else {\n // Not in a list → create new OL via execCommand\n execCommand('insertOrderedList');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Line-height helper\n// ---------------------------------------------------------------------------\n\n/**\n * Set the line-height on every block-level element that intersects the current selection.\n *\n * If the selection is collapsed, the nearest enclosing block element receives the style.\n * For a non-collapsed selection, all unique block ancestors of text nodes that intersect the range are updated;\n * if none are found, the nearest block ancestor of the range's common ancestor is updated.\n * @param {string} value - Line-height value to apply; typically a unitless multiplier (for example, \"1.5\").\n */\nexport function lineHeight(value) {\n const sel = globalThis.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.createTreeWalker(\n range.commonAncestorContainer,\n NodeFilter.SHOW_TEXT,\n { acceptNode: (node) => range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP },\n );\n let textNode;\n while ((textNode = iter.nextNode())) {\n const block = nearestBlock(textNode);\n if (block) blocks.add(block);\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 = /** @type {Element|null} */ (isElement(container) ? container : container.parentElement);\n if (!el) return {};\n\n const computed = globalThis.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 = globalThis.getSelection();\n if (!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 = /** @type {Element|null} */ (container)?.closest('code');\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 codeEl.remove();\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 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.at(-1);\n const nr = document.createRange();\n // Use the (possibly merged) live node if still in the DOM.\n const anchorNode = firstMoved.parentNode === parent\n ? firstMoved\n : (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 (_) { void _; /* 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 = globalThis.getSelection();\n if (!sel?.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n const code = /** @type {Element|null} */ (sc)?.closest('code');\n return !!(code && !code.closest('pre'));\n}\n\n// ---------------------------------------------------------------------------\n// Checklist (task list)\n// ---------------------------------------------------------------------------\n\n/**\n * Changes the tag name of an element in the DOM while preserving attributes and children.\n * @param {Element} el\n * @param {string} newTagName\n * @returns {HTMLElement}\n */\nfunction changeTagName(el, newTagName) {\n const newEl = document.createElement(newTagName);\n for (const attr of el.attributes) {\n newEl.setAttribute(attr.name, attr.value);\n }\n while (el.firstChild) {\n newEl.appendChild(el.firstChild);\n }\n el.parentNode.replaceChild(newEl, el);\n return newEl;\n}\n\n/**\n * Ensures all list items under the list element have a checkbox.\n * @param {Element} listEl\n */\nfunction ensureCheckboxes(listEl) {\n listEl.querySelectorAll('li').forEach(li => {\n const existingCb = li.querySelector('input[type=\"checkbox\"]');\n if (!existingCb) {\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.contentEditable = 'false';\n li.insertBefore(cb, li.firstChild);\n }\n });\n}\n\n/**\n * Toggle a checklist at the current selection or caret.\n */\nexport function toggleChecklist() {\n const sel = globalThis.getSelection();\n if (!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 listEl = /** @type {Element|null} */ (container)?.closest('ul, ol');\n if (listEl) {\n if (listEl.classList.contains('an-checklist')) {\n // Transition from Checklist to Paragraphs (Toggle off checklist entirely)\n const parent = listEl.parentNode;\n if (parent) {\n const lis = Array.from(listEl.children);\n let /** @type {HTMLParagraphElement|null} */ firstP = null;\n lis.forEach(li => {\n const p = document.createElement('p');\n for (const child of li.childNodes) {\n if (child.nodeType === 1 && /** @type {Element} */ (child).tagName === 'INPUT') continue;\n p.appendChild(child.cloneNode(true));\n }\n p.innerHTML = p.innerHTML.replaceAll('\\u200b', '').replaceAll('\\u200B', '');\n if (!p.hasChildNodes() || !p.textContent.trim()) {\n p.innerHTML = '';\n p.appendChild(document.createTextNode('\\u00a0'));\n }\n listEl.before(p);\n if (!firstP) firstP = p;\n });\n listEl.remove();\n \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 }\n } else {\n // Transition from standard UL/OL to Checklist\n const targetUl = changeTagName(listEl, 'ul');\n targetUl.classList.add('an-checklist');\n ensureCheckboxes(targetUl);\n \n // Place caret inside the first LI\n const firstLi = targetUl.querySelector('li');\n if (firstLi) {\n const nr = document.createRange();\n nr.selectNodeContents(firstLi);\n nr.collapse(false);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n }\n } else {\n // Selection is not in a list: build the checklist directly via DOM\n // manipulation. execCommand('insertUnorderedList') is intentionally\n // avoided here — its behaviour on collapsed/empty selections and\n // non-standard blocks (e.g. <section>) is too inconsistent across\n // browsers (and a no-op in jsdom), which left toggleChecklist() as a\n // silent no-op in those cases.\n // The editable root itself is a <div> and must never be treated as a\n // \"block\" to convert/replace/remove — otherwise selections that include\n // raw text nodes sitting directly inside it (e.g. the first line typed\n // into an empty editor) would destroy the .an-editable element.\n const editableRoot = /** @type {Element|null} */ (container)?.closest('[contenteditable=\"true\"]');\n const isCollapsed = range.collapsed;\n if (isCollapsed) {\n // Find the nearest block-level ancestor (p, div, li, h1-h6, blockquote,\n // etc.) 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 = /** @type {Element|null} */ (container);\n while (block?.parentNode && block !== editableRoot && !BLOCK_TAGS.has(block.tagName)) {\n block = /** @type {Element|null} */ (block.parentNode);\n }\n if (block === editableRoot) block = null;\n // Fallback: if no block element found (e.g. cursor directly in editable\n // root), insert a fresh item with a zero-width-space so the cursor ends\n // up inside it.\n const itemText = (block && BLOCK_TAGS.has(block.tagName))\n ? Array.from(block.childNodes)\n .map((n) => n.textContent)\n .join('')\n .replaceAll('\\u00a0', ' ')\n : '';\n\n const newUl = document.createElement('ul');\n newUl.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 newUl.appendChild(li);\n\n if (block && BLOCK_TAGS.has(block.tagName)) {\n block.parentNode.replaceChild(newUl, block);\n } else {\n // Cursor directly in editable root — insert via Range API.\n const nativeRange = sel.getRangeAt(0);\n nativeRange.deleteContents();\n nativeRange.insertNode(newUl);\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 // Non-collapsed selection — convert each intersected block element into\n // a checklist item using direct DOM manipulation.\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 blockEl = /** @type {Element|null} */ (node.nodeType === Node.TEXT_NODE ? node.parentElement : node);\n while (blockEl && blockEl !== editableRoot && !BLOCK_TAGS_MULTI.has(blockEl.tagName)) {\n blockEl = blockEl.parentElement;\n }\n if (blockEl === editableRoot) blockEl = null;\n if (blockEl && !seenBlocks.has(blockEl)) {\n seenBlocks.add(blockEl);\n blocks.push(blockEl);\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 /** @type {Text|null} */ 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.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.remove());\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/**\n * Returns true when the cursor is inside a checklist item.\n * @returns {boolean}\n */\nexport function isInChecklist() {\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return false;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n return !!(/** @type {Element|null} */ (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 {Array<string|{value:string,label:string,disabled?:boolean}>} [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 * @property {string} [selectClass] - extra CSS class(es) for the <select>\n * @property {string} [placeholder] - placeholder text for the empty option\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// Global button registry\n// ---------------------------------------------------------------------------\n\n/**\n * Global registry for custom buttons registered via AutumnNote.registerButton()\n * or via a plugin's `buttons` array. Toolbar resolves string names from here.\n * @type {Map<string, object>}\n */\nexport const _buttonRegistry = new Map();\n\n/**\n * Registers a button definition in the global registry so it can be referenced\n * by string name in toolbar configuration: `toolbar: [['myBtn', boldBtn]]`.\n * @param {object} btnDef - Any ToolbarItemDef-compatible object with a `name` string.\n */\nexport function registerButton(btnDef) {\n if (!btnDef || typeof btnDef.name !== 'string') {\n console.warn('[AutumnNote] registerButton: btnDef must have a string `name` property.');\n return;\n }\n if (_buttonRegistry.has(btnDef.name)) {\n console.warn(`[AutumnNote] registerButton: overwriting existing button \"${btnDef.name}\".`);\n }\n _buttonRegistry.set(btnDef.name, btnDef);\n}\n\n/**\n * Looks up a button definition by name from the global registry.\n * Returns undefined when not found.\n * @param {string} name\n * @returns {object|undefined}\n */\nexport function getButton(name) {\n return _buttonRegistry.get(name);\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 = globalThis.getSelection();\n if (!sel?.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n return !!(/** @type {Element} */ (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 = globalThis.getSelection();\n if (sel?.rangeCount) {\n let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);\n if (el?.nodeType === 3) el = el.parentElement;\n while (el?.nodeType === 1 && !/** @type {HTMLElement} */ (el).style.fontSize) el = el.parentElement;\n const size = /** @type {HTMLElement} */ (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?.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 = globalThis.getSelection();\n if (!sel?.rangeCount) return '';\n const BLOCKS = new Set(['P','DIV','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE','PRE','TD','TH']);\n let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);\n if (el?.nodeType === 3) el = el.parentElement;\n while (el && !BLOCKS.has(/** @type {Element} */ (el).tagName)) el = el.parentElement;\n if (!el) return '';\n return /** @type {HTMLElement} */ (el).style.lineHeight || getComputedStyle(/** @type {Element} */ (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// ---------------------------------------------------------------------------\n// Buttons namespace — all pre-built button definitions in a single object.\n// Exposed as AutumnNote.buttons so UMD / CJS consumers can access them\n// without named imports: AutumnNote.buttons.boldBtn, etc.\n// ---------------------------------------------------------------------------\n\nexport const buttons = {\n boldBtn,\n italicBtn,\n underlineBtn,\n strikeBtn,\n superscriptBtn,\n subscriptBtn,\n alignLeftBtn,\n alignCenterBtn,\n alignRightBtn,\n alignJustifyBtn,\n ulBtn,\n olBtn,\n indentBtn,\n outdentBtn,\n undoBtn,\n redoBtn,\n hrBtn,\n linkBtn,\n imageBtn,\n videoBtn,\n emojiBtn,\n iconBtn,\n tableBtn,\n fontSizeBtn,\n removeFormatBtn,\n directionBtn,\n fontFamilyBtn,\n paragraphStyleBtn,\n lineHeightBtn,\n codeviewBtn,\n fullscreenBtn,\n shortcutsBtn,\n findBtn,\n findReplaceBtn,\n inlineCodeBtn,\n checklistBtn,\n printBtn,\n foreColorBtn,\n backColorBtn,\n defaultToolbar,\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} [useBootstrap] - Use Bootstrap button classes on toolbar buttons\n * @property {string} [toolbarButtonClass] - CSS classes for Bootstrap toolbar buttons\n * @property {boolean} [useFontAwesome] - Use Font Awesome icons (default: true)\n * @property {string} [fontAwesomeClass] - Font Awesome prefix class, e.g. 'fas' or 'fa-solid'\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 {number} [historyLimit] - Maximum undo/redo history steps\n * @property {number} [historyMaxBytes] - Maximum combined size (chars) of all stacked undo/redo snapshots\n * @property {string} [defaultFontFamily] - Default font family applied to the editable area on init\n * @property {string} [defaultFontSize] - Default font size applied to the editable area on init (e.g. '14px')\n * @property {string[]} [fontFamilies] - Font families shown in the font-family toolbar dropdown\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} [onInit] - Callback after the editor has initialised\n * @property {Function} [onImageUpload] - Custom upload handler: (files) => void\n * @property {Function} [onImageError] - Callback when an image upload error occurs\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} [autoSaveDelay] - Debounce delay for auto-save writes in milliseconds\n * @property {object|null} [autoSaveAdapter] - Optional async persistence adapter with save/load/remove methods\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} [onPasteError] - Callback fired when pasted or dropped content cannot be processed\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 * @property {boolean} [autoSaveRestore] - Show a restore banner when a previously auto-saved draft exists\n * @property {number} [autoSaveRestoreTimeout] - Maximum age in days for a draft to be offered for restore (0 = no expiry)\n * @property {Function} [onAutoSaveRestore] - Callback fired after the user chooses to restore a draft\n * @property {boolean} [markdownShortcuts] - Convert markdown syntax typed inline to HTML\n * @property {boolean} [bubbleToolbar] - Show a mini floating toolbar above text selections\n * @property {string[]} [bubbleToolbarItems] - Button names for the bubble toolbar\n * @property {object|null} [mention] - @mention configuration (onSearch, minChars, ...)\n * @property {boolean} [slashMenu] - Show a \"/\" command palette for quick block insertion (default true)\n * @property {string} [lang] - Display language or partial locale object override\n */\n\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 // Max combined size (chars) of all stacked undo/redo snapshots. Guards\n // against documents with many large embedded images holding dozens of\n // full-size copies in memory despite historyLimit.\n historyMaxBytes: 10 * 1024 * 1024,\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 autoSaveDelay: 400,\n autoSaveAdapter: null,\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 for rejected/failed paste and drop payloads: function({ message, size?, maxBytes? })\n onPasteError: 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', 'de', 'es', 'ko'.\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 // \"/\" command palette for quick block insertion (headings, lists, table, image, ...).\n // Triggers only when \"/\" is the first character typed on an otherwise-empty line.\n slashMenu: true,\n // Additional slash-menu commands supplied by applications/plugins.\n slashCommands: [],\n\n // Optional import/export adapters keyed by format name.\n documentAdapters: {},\n // Optional collaboration bridge notified with local HTML changes.\n collaborationAdapter: null,\n\n // Optional image processor (for example a Web Worker bridge). Receives a\n // File and returns a data URL; Clipboard's canvas pipeline remains fallback.\n imageProcessor: null,\n // Add stable data-an-block-id attributes to top-level document blocks.\n blockIds: false,\n\n // Maximum paste size in bytes (default 5 MB). Pastes larger than this are silently dropped.\n maxPasteSize: 5 * 1024 * 1024,\n // Minimum image dimension in px during resize (width and height). Prevents images from being\n // resized below this value.\n minImageSize: 20,\n\n // Bubble toolbar: show a mini floating toolbar above text selections.\n bubbleToolbar: false,\n bubbleToolbarItems: ['bold', 'italic', 'underline', 'link', 'foreColor', 'hiliteColor', '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 wholeWord: 'Whole Word',\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 noResults: 'No results',\n useRegex: 'Use Regular Expression',\n close: '\\u00d7',\n },\n\n autoSaveRestore: {\n found: 'Draft found. Restore?',\n foundAt: 'Draft from {date}. Restore?',\n restore: 'Restore',\n discard: 'Discard',\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 lineNumbers: 'Toggle Line Numbers',\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 tableBorderColor: 'Table Border Color',\n deleteTable: 'Delete Table',\n cellAlignLeft: 'Align Left',\n cellAlignCenter: 'Align Center',\n cellAlignRight: 'Align Right',\n cellAlignJustify: 'Align Justify',\n toggleHeaderRow: 'Toggle Header Row',\n cellBackground: 'Cell Background',\n noShading: 'No Shading',\n noBorderColor: 'No Border Color',\n columnWidthPx: 'Column Width (px)',\n rowHeightPx: 'Row Height (px)',\n tableBorderWidthPx: 'Table Border Width (px)',\n cancelBtn: 'Cancel',\n applyBtn: 'Apply',\n sortAsc: 'Sort Ascending',\n sortDesc: 'Sort Descending',\n exportCSV: 'Export as CSV',\n cellPadding: 'Cell Padding',\n cellPaddingPx: 'Cell Padding (px)',\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 slashMenu: {\n noResults: 'No matching commands',\n heading1: 'Heading 1',\n heading2: 'Heading 2',\n heading3: 'Heading 3',\n bulletList: 'Bullet List',\n numberedList: 'Numbered List',\n checklist: 'Checklist',\n blockquote: 'Blockquote',\n codeBlock: 'Code Block',\n horizontalRule: 'Horizontal Rule',\n table: 'Table',\n image: 'Image',\n },\n};\n","/**\n * i18n/index.js — Locale registry and resolver for autumn-note-ce.\n *\n * Only English ships in the ESM bundle. Bundling all eight locales cost every\n * consumer ~15 KB gzip even when they only ever rendered English, so the other\n * locales are opt-in via subpath imports:\n *\n * import AutumnNote from 'autumnnote';\n * import { vi } from 'autumnnote/i18n/vi';\n *\n * AutumnNote.registerLocale('vi', vi);\n * AutumnNote.create('#editor', { lang: 'vi' });\n *\n * The UMD/CDN build cannot tree-shake, so it pre-registers every locale and\n * `lang: 'vi'` keeps working there with no extra imports.\n *\n * Usage:\n * lang: 'en' → built-in English (always available)\n * lang: '<code>' → a locale previously passed to registerLocale()\n * lang: { ... } → custom locale object, deep-merged over English\n */\n\nimport { mergeDeep } from '../core/func.js';\nimport { en } from './en.js';\n\n/**\n * Locales available to `lang: '<code>'`. Starts with English only; other codes\n * are added through {@link registerLocale}.\n * @type {Record<string, Partial<AsnLocale>>}\n */\nexport const locales = { en };\n\n/**\n * Registers a locale so it can be selected by code.\n *\n * @param {string} code - Language code, e.g. 'vi'.\n * @param {Partial<AsnLocale>} locale - Locale object; missing keys fall back to English.\n * @returns {void}\n */\nexport function registerLocale(code, locale) {\n if (typeof code !== 'string' || !code) {\n throw new TypeError('[AutumnNote] registerLocale: code must be a non-empty string.');\n }\n if (!locale || typeof locale !== 'object') {\n throw new TypeError(`[AutumnNote] registerLocale: locale for \"${code}\" must be an object.`);\n }\n locales[code] = locale;\n}\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 if (!partial) {\n // Unregistered code → English, but say why: silently rendering English\n // after asking for another language is confusing to debug.\n console.warn(\n `[AutumnNote] Locale \"${lang}\" is not registered, falling back to English. ` +\n `Import it first: import { ${lang} } from 'autumnnote/i18n/${lang}'; ` +\n `AutumnNote.registerLocale('${lang}', ${lang});`,\n );\n return en;\n }\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', 'base', 'template', 'link', 'meta', 'noscript', 'portal', 'frame', 'frameset', 'applet'];\n\n/** Tags whose element wrapper is stripped but content (child nodes) is preserved. */\nconst UNWRAP_TAGS = new Set(['button']);\n\n/** Attributes whose values must be sanitised as URLs. */\nconst URL_ATTRS = ['href', 'src', 'action', 'formaction', 'xlink:href'];\n\n/** Inline style properties the editor's own toolbar/table features persist on saved content. */\nconst ALLOWED_STYLE_PROPS = new Set([\n 'color', 'background-color', 'font-size', 'line-height',\n 'text-align', 'vertical-align',\n 'width', 'min-width', 'height', 'min-height',\n 'border-width', 'border-style', 'border-color', 'padding',\n]);\n\n/** Value patterns that are never safe regardless of property. */\nconst DANGEROUS_STYLE_VALUE_RE = /url\\s*\\(|expression\\s*\\(|@import|javascript:|vbscript:|behavior\\s*:|-moz-binding/i;\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\nconst SAFE_LINK_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:']);\nconst SAFE_MEDIA_PROTOCOLS = new Set(['http:', 'https:', 'blob:']);\nconst SAFE_RASTER_DATA_RE = /^data:image\\/(?:png|jpe?g|gif|webp|avif|bmp);base64,[a-z0-9+/=\\s]+$/i;\nconst URL_BASE = 'https://autumnnote.invalid/';\n\n/**\n * Produce a sanitized HTML string with dangerous elements and attributes removed.\n *\n * Removes disallowed tags and wrappers, strips event-handler attributes, rejects\n * `javascript:`/`vbscript:` URLs and most `data:` URIs, restricts iframe `src`\n * to trusted hosts when enabled, and permits only checklist checkboxes as inputs.\n *\n * @param {string} html - HTML fragment to sanitize.\n * @param {Object} [options]\n * @param {boolean} [options.allowIframes=false] - If true, `iframe` elements are not removed but their `src` is restricted to trusted hosts and `srcdoc` is removed.\n * @returns {string} The sanitized HTML fragment.\n */\nexport function sanitiseHTML(html, { allowIframes = false } = {}) {\n const doc = new DOMParser().parseFromString(`<body>${html || ''}</body>`, 'text/html');\n\n // Single querySelectorAll pass — collect all elements once to avoid\n // repeated full-tree traversals for each category of check.\n const allElements = Array.from(doc.querySelectorAll('*'));\n\n // Build the prohibited tag set for fast O(1) lookup\n const prohibited = new Set(\n allowIframes ? PROHIBITED_TAGS.filter((t) => t !== 'iframe') : PROHIBITED_TAGS,\n );\n\n for (const el of allElements) {\n const tag = el.tagName.toLowerCase();\n\n // Unwrap elements whose wrapper is unsafe but whose content should be kept\n if (UNWRAP_TAGS.has(tag)) {\n el.replaceWith(...el.childNodes);\n continue;\n }\n\n // Remove outright dangerous elements\n if (prohibited.has(tag)) {\n el.remove();\n continue;\n }\n\n // Invalid embeds are removed rather than retained as empty iframes.\n if (tag === 'iframe') {\n const src = el.getAttribute('src');\n if (!src || !isTrustedIframeSrc(src)) {\n el.remove();\n continue;\n }\n }\n\n // Strip dangerous attributes\n for (const attr of Array.from(el.attributes)) {\n // Remove all event handlers (onclick, onload, onerror, …)\n if (attr.name.startsWith('on')) {\n el.removeAttribute(attr.name);\n continue;\n }\n // Filter the style attribute down to an allowlisted set of safe\n // properties (see ALLOWED_STYLE_PROPS) — not a blanket strip, since\n // the editor's own toolbar/table features persist inline styles\n // (text color/highlight, font size, line height, table alignment/\n // sizing/borders) that must survive sanitisation.\n if (attr.name === 'style') {\n const cleaned = sanitiseStyleValue(attr.value);\n if (cleaned) el.setAttribute('style', cleaned);\n else el.removeAttribute('style');\n continue;\n }\n // Sanitise URL attributes\n if (URL_ATTRS.includes(attr.name)) {\n const val = attr.value.trim();\n const isMediaSource = attr.name === 'src' &&\n ['IMG', 'VIDEO', 'AUDIO', 'SOURCE'].includes(el.tagName);\n if (!isSafeUrl(val, { media: isMediaSource, allowData: el.tagName === 'IMG' })) {\n el.removeAttribute(attr.name);\n continue;\n }\n }\n // Strip iframe HTML-injection vectors; limit src to trusted hosts\n if (el.tagName === 'IFRAME') {\n if (attr.name === 'srcdoc') {\n el.removeAttribute(attr.name);\n continue;\n }\n if (attr.name === 'src' && !isTrustedIframeSrc(attr.value)) {\n el.removeAttribute(attr.name);\n }\n }\n }\n\n if (tag === 'a' && el.getAttribute('target') === '_blank') {\n el.setAttribute('rel', 'noopener noreferrer');\n }\n\n // Allow only input[type=\"checkbox\"] inside ul.an-checklist li\n if (tag === 'input') {\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 for (const attr of Array.from(el.attributes)) {\n if (!['type', 'checked', 'contenteditable'].includes(attr.name)) {\n el.removeAttribute(attr.name);\n }\n }\n }\n }\n }\n\n return doc.body.innerHTML;\n}\n\n/**\n * Filters a style attribute value down to an allowlisted set of CSS\n * properties (ALLOWED_STYLE_PROPS), dropping any declaration whose value\n * contains a dangerous construct — url(), expression(), an \"import\" rule,\n * javascript:/vbscript:, IE behavior/-moz-binding — regardless of property.\n * @param {string} value\n * @returns {string} The filtered declaration list, or '' if nothing survives.\n */\nfunction sanitiseStyleValue(value) {\n const kept = [];\n for (const decl of (value || '').split(';')) {\n const idx = decl.indexOf(':');\n if (idx === -1) continue;\n const prop = decl.slice(0, idx).trim().toLowerCase();\n const val = decl.slice(idx + 1).trim();\n if (!prop || !val) continue;\n if (!ALLOWED_STYLE_PROPS.has(prop)) continue;\n if (DANGEROUS_STYLE_VALUE_RE.test(val)) continue;\n kept.push(`${prop}: ${val}`);\n }\n return kept.join('; ');\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, media?: boolean }} [opts]\n * @returns {string|null} The original URL if safe, null if rejected.\n */\nexport function sanitiseUrl(url, { allowData = false, media = allowData } = {}) {\n const trimmed = (url || '').trim();\n if (!trimmed && url == null) return null;\n return isSafeUrl(trimmed, { media, allowData }) ? url : null;\n}\n\n/**\n * Validate a URL using the browser URL parser so ASCII whitespace/control\n * characters cannot disguise a dangerous protocol (for example java\\nscript:).\n * @param {string} value\n * @param {{media?: boolean, allowData?: boolean}} [options]\n * @returns {boolean}\n */\nfunction isSafeUrl(value, { media = false, allowData = false } = {}) {\n const trimmed = (value || '').trim();\n if (!trimmed) return true;\n if (allowData && SAFE_RASTER_DATA_RE.test(trimmed)) return true;\n\n try {\n const parsed = new URL(trimmed, URL_BASE);\n const protocols = media ? SAFE_MEDIA_PROTOCOLS : SAFE_LINK_PROTOCOLS;\n return protocols.has(parsed.protocol);\n } catch {\n return false;\n }\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 (_) { void _; }\n }\n if (!initialContent) {\n initialContent = targetEl.tagName === 'TEXTAREA'\n ? ((/** @type {HTMLTextAreaElement} */ (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?.[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 theme — also add to body so floating elements (dialogs, tooltips,\n // popovers) appended to document.body inherit the CSS rules.\n if (options.theme === 'dark') {\n container.classList.add('an-theme-dark');\n document.body.classList.add('an-theme-dark');\n } else if (options.theme === 'auto') {\n container.classList.add('an-theme-auto');\n document.body.classList.add('an-theme-auto');\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.after(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 * @param {number} [maxBytes=10485760] - maximum combined size (chars) of all\n * stacked snapshots (html + tokenized image data). Oldest states are\n * evicted first when exceeded, even if `limit` hasn't been reached —\n * documents with many large embedded images can otherwise hold dozens of\n * full-size copies in memory despite the step-count limit.\n */\n constructor(editable, limit = 100, maxBytes = 10 * 1024 * 1024) {\n this.editable = editable;\n this._limit = limit;\n this._maxBytes = maxBytes;\n this._bytes = 0;\n /** @type {Array<{html: string, images?: Record<string,string>, sel: {start: number, end: number}|null}>} */\n this.stack = [];\n this.stackOffset = -1;\n this._savePoint();\n }\n\n /**\n * Approximate in-memory size (chars) of one stacked snapshot: the tokenized\n * HTML string plus every image data URL it references.\n * @param {{html: string, images?: Record<string,string>}} entry\n * @returns {number}\n */\n _entrySize(entry) {\n let size = entry.html.length;\n if (entry.images) {\n for (const key in entry.images) size += entry.images[key].length;\n }\n return size;\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 = globalThis.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 += /** @type {Text} */ (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 = /** @type {Text} */ (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 ? /** @type {Text} */ (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 = globalThis.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_) {\n void _; // detached node — fall back to placing cursor at start of editable\n try {\n const fb = document.createRange();\n fb.setStart(this.editable, 0);\n fb.collapse(true);\n const s = globalThis.getSelection();\n if (s) { s.removeAllRanges(); s.addRange(fb); }\n } catch (_2) { void _2; /* fully give up */ }\n }\n }\n\n _savePoint() {\n // Trim future history if we're mid-stack\n if (this.stackOffset < this.stack.length - 1) {\n for (const entry of this.stack.slice(this.stackOffset + 1)) {\n this._bytes -= this._entrySize(entry);\n }\n this.stack = this.stack.slice(0, this.stackOffset + 1);\n }\n const raw = this._serialize();\n const { html, images } = this._tokenizeImages(raw);\n const entry = { html, images, sel: this._serializeSelection() };\n this.stack.push(entry);\n this._bytes += this._entrySize(entry);\n\n // Evict oldest states first, whichever budget (step count or byte size)\n // is exceeded — always keep at least the just-pushed current state.\n while (this.stack.length > 1 && (this.stack.length > this._limit || this._bytes > this._maxBytes)) {\n this._bytes -= this._entrySize(this.stack.shift());\n }\n // The newly-pushed current state is always the final entry. Recompute the\n // offset from the resulting stack instead of incrementing conditionally:\n // a single oversized snapshot may evict several older entries at once.\n this.stackOffset = this.stack.length - 1;\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 // Fast-path: skip regex entirely when there are no data URIs (common case)\n if (!html.includes('data:')) return { html, images: /** @type {Record<string,string>} */ ({}) };\n const images = /** @type {Record<string,string>} */ ({});\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?.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._bytes = 0;\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 /** @returns {number} */\n getUndoCount() {\n return Math.max(0, this.stackOffset);\n }\n\n /** @returns {number} */\n getRedoCount() {\n return Math.max(0, this.stack.length - 1 - this.stackOffset);\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';\n\n// ---------------------------------------------------------------------------\n// Table creation\n// ---------------------------------------------------------------------------\n\n/**\n * Build an HTML table with the given number of columns and rows, optionally including a header row.\n * @param {number} cols - Number of columns in each row.\n * @param {number} rows - Total number of rows to create (including header when `headerRow` is true).\n * @param {{ headerRow?: boolean }} [opts] - Options: `headerRow` creates a `<thead>` when true.\n * @returns {HTMLTableElement} The constructed `<table>` element with a `<tbody>` and optional `<thead>`; each cell contains a `<br>` placeholder.\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', {}, [document.createElement('br')]);\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', {}, [document.createElement('br')]);\n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n return /** @type {HTMLTableElement} */ (table);\n}\n\n/**\n * Insert a table at the current selection and place the caret into its first cell.\n * @param {number} cols - Number of columns for the new table.\n * @param {number} rows - Number of rows for the new table.\n * @param {{ headerRow?: boolean }} [opts] - Options for table creation.\n */\nexport function insertTable(cols, rows, opts = {}) {\n if (cols <= 0 || rows <= 0) return;\n const table = createTable(cols, rows, opts);\n\n const sel = globalThis.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n try {\n range.deleteContents();\n } catch (_) {\n return;\n }\n\n // Walk up to find the nearest block-level ancestor to insert after\n const BLOCK = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI', 'PRE']);\n let anchor = /** @type {Element|null} */ (range.startContainer);\n if (anchor?.nodeType === 3) anchor = anchor.parentElement;\n while (anchor && !BLOCK.has(anchor.tagName?.toUpperCase()) && anchor.parentElement) {\n anchor = anchor.parentElement;\n }\n\n if (anchor && BLOCK.has(anchor.tagName?.toUpperCase()) && anchor.parentNode) {\n anchor.after(table);\n // Ensure there's a paragraph after the table for cursor landing\n if (!table.nextElementSibling) {\n const p = document.createElement('p');\n p.appendChild(document.createElement('br'));\n table.after(p);\n }\n // Remove the anchor block if it was empty (common case: cursor in blank paragraph)\n if (!anchor.textContent.trim() && !anchor.querySelector('img, video, table')) {\n anchor.remove();\n }\n } else {\n try {\n range.insertNode(table);\n } catch (_) {\n return;\n }\n }\n\n // Place cursor in the first cell\n const firstCell = table.querySelector('td, th');\n if (firstCell) {\n const nr = document.createRange();\n nr.setStart(firstCell, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\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?.nodeName === 'I' && _FA_PATTERN.test(n.className || ''));\nconst isZwsAnchor = (n) => !!(n?.nodeType === Node.TEXT_NODE && (n.textContent === '\\u200B' || n.textContent === ''));\n\n/**\n * Extracts the content from `startContainer:startOffset` to the end of `li`.\n * Returns an empty fragment if the range is invalid (e.g. detached node).\n * @param {Range} nativeRange\n * @param {Element} li\n * @returns {DocumentFragment}\n */\nfunction extractAfterContent(nativeRange, li) {\n try {\n const r = document.createRange();\n r.setStart(nativeRange.startContainer, nativeRange.startOffset);\n r.setEnd(li, li.childNodes.length);\n return r.extractContents();\n } catch (_) {\n void _;\n return document.createDocumentFragment();\n }\n}\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 = globalThis.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 = globalThis.getSelection();\n if (sel?.rangeCount > 0) {\n const r = sel.getRangeAt(0);\n if (r.collapsed && r.startContainer.nodeType === Node.TEXT_NODE) {\n const textNode = /** @type {ChildNode} */ (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 /** @type {ChildNode} */ (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 = /** @type {ChildNode} */ (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?.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 = globalThis.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?.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?.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?.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?.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 using configured tabSize\n if (para?.nodeName.toUpperCase() === 'PRE') {\n if (event.shiftKey) return false;\n event.preventDefault();\n execCommand('insertText', ' '.repeat(options.tabSize || 4));\n return true;\n }\n\n // Default: insert &nbsp; * 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 = /** @type {Element|null} */ (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?.nodeName === 'I' && /\\bfa-/.test(el.className || '')) {\n const nr = document.createRange();\n nr.setStartAfter(el);\n nr.collapse(true);\n const selI = globalThis.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?.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 = globalThis.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?.closest('.an-checklist li');\n if (checkLi) {\n event.preventDefault();\n const ul = checkLi.closest('.an-checklist');\n const sel = globalThis.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 if (sel.rangeCount === 0 || !checkLi.isConnected) return true;\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 afterFrag = extractAfterContent(nativeRange, checkLi);\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?.nodeType !== Node.TEXT_NODE) {\n cursorNode = document.createTextNode('\\u200B');\n newLi.appendChild(cursorNode);\n }\n checkLi.after(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 // Enter in a pre/code block: insert a literal newline instead of a new block\n if (para?.nodeName.toUpperCase() === 'PRE') {\n event.preventDefault();\n execCommand('insertText', '\\n');\n return true;\n }\n\n // Pressing Enter at the end of a blockquote should exit it\n if (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\n/**\n * Convert a DOM node subtree into Markdown.\n *\n * Recursively produces a Markdown string representing the given DOM node and its descendants,\n * handling common HTML constructs such as paragraphs, headings, lists (with nested indentation),\n * blockquotes, fenced and inline code, links, images, tables, horizontal rules, and basic inline emphasis.\n *\n * @param {Node} node - The DOM node to convert.\n * @param {number} [depth=0] - Current nesting depth used to indent nested list items.\n * @returns {string} The Markdown representation of the node subtree.\n */\n/**\n * Direct child elements matching a tag name. Used instead of the CSS\n * `:scope > tag` combinator, which this project's jsdom version resolves\n * incorrectly (matches descendants at any depth, not just direct children).\n * @param {Element} el\n * @param {string} tagName\n * @returns {Element[]}\n */\nfunction _directChildren(el, tagName) {\n return Array.from(el.children).filter((c) => c.tagName === tagName.toUpperCase());\n}\n\nfunction _domToMd(node, depth = 0) {\n if (node.nodeType === 3) {\n return node.textContent.replace(/\\s+/g, ' ');\n }\n if (node.nodeType !== 1) return '';\n\n const el = /** @type {Element} */ (node);\n const tag = el.nodeName.toLowerCase();\n const inner = () => Array.from(el.childNodes).map(n => _domToMd(n, depth)).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 'u': return `<u>${inner()}</u>`;\n case 'span': {\n // Markdown has no native underline/color/size syntax; pass through as\n // raw inline HTML for the specific styles the editor's own toolbar\n // creates (foreColor/backColor/fontSize) — other noise spans (e.g. from\n // pasted content) are unwrapped to plain text as before.\n const style = el.getAttribute('style') || '';\n if (/\\b(color|background-color|font-size)\\s*:/.test(style)) {\n return `<span style=\"${_escAttr(style)}\">${inner()}</span>`;\n }\n return inner();\n }\n case 'code': {\n // Inside <pre> we emit raw text; outside we wrap in backticks\n if (el.closest('pre')) return inner();\n return `\\`${inner()}\\``;\n }\n case 'pre': {\n const codeEl = el.querySelector('code');\n const langMatch = /language-(\\S+)/.exec(codeEl?.className || '');\n const lang = langMatch ? langMatch[1] : '';\n const content = (codeEl || el).textContent || '';\n return `\\n\\n\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n\\n`;\n }\n case 'blockquote': {\n const rawLines = inner().trim().split('\\n');\n // Collapse consecutive blank lines (from adjacent <p> blocks) into one.\n const lines = rawLines.filter((l, idx) => l.trim() !== '' || (rawLines[idx - 1] ?? '').trim() !== '');\n return `\\n\\n${lines.map((l) => (l.trim() === '' ? '>' : `> ${l}`)).join('\\n')}\\n\\n`;\n }\n case 'a': {\n const href = el.getAttribute('href') || '';\n return `[${inner()}](${href})`;\n }\n case 'img': {\n const src = el.getAttribute('src') || '';\n const alt = el.getAttribute('alt') || '';\n return `![${alt}](${src})`;\n }\n case 'ul': {\n const items = _directChildren(el, 'li');\n if (!items.length) return inner();\n const indent = ' '.repeat(depth);\n const isChecklist = el.classList.contains('an-checklist');\n const lines = items.map((li) => {\n const cb = /** @type {HTMLInputElement | undefined} */ (\n _directChildren(li, 'input').find((c) => c.getAttribute('type') === 'checkbox')\n );\n let prefix = '- ';\n if (isChecklist || cb) {\n const checked = cb ? cb.checked : false;\n prefix = checked ? '- [x] ' : '- [ ] ';\n }\n return `${indent}${prefix}${_domToMd(li, depth + 1).trim()}`;\n }).join('\\n');\n return depth === 0 ? `\\n\\n${lines}\\n\\n` : `\\n${lines}`;\n }\n case 'ol': {\n const items = _directChildren(el, 'li');\n if (!items.length) return inner();\n const indent = ' '.repeat(depth);\n const lines = items.map((li, i) => `${indent}${i + 1}. ${_domToMd(li, depth + 1).trim()}`).join('\\n');\n return depth === 0 ? `\\n\\n${lines}\\n\\n` : `\\n${lines}`;\n }\n case 'li': return inner();\n case 'hr': return '\\n\\n---\\n\\n';\n case 'table': {\n const allRows = Array.from(el.querySelectorAll('tr'));\n if (!allRows.length) return inner();\n const theadEl = _directChildren(el, 'thead')[0];\n const firstRowIsHeader = !!theadEl || (\n allRows[0].children.length > 0 &&\n Array.from(allRows[0].children).every((c) => c.tagName === 'TH')\n );\n const cellTexts = allRows.map((tr) =>\n Array.from(tr.querySelectorAll('th, td')).map((c) => c.textContent.trim().replaceAll('|', String.raw`\\|`)),\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 const bodyStart = firstRowIsHeader ? 1 : 0;\n const headerCells = firstRowIsHeader ? padRow(cellTexts[0]) : new Array(cols).fill('');\n let md = '\\n\\n';\n md += `| ${headerCells.join(' | ')} |\\n`;\n md += `| ${new Array(cols).fill('---').join(' | ')} |\\n`;\n for (let r = bodyStart; 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 * Detects whether a string likely contains Markdown syntax.\n *\n * Checks for common Markdown constructs such as ATX headings, unordered or\n * ordered list items, blockquotes, fenced code blocks, and bold emphasis.\n * @param {string} text - Input text to inspect for Markdown patterns.\n * @returns {boolean} `true` if any Markdown-like pattern is present, `false` otherwise.\n */\nexport function isMarkdown(text) {\n return /^#{1,6} [^\\s]|^[ \\t]*[-*+] [^\\s]|^[ \\t]*\\d+\\. [^\\s]|^> ?[^\\s]|^```|^\\*{2}[^*\\n]+\\*{2}/m.test(text)\n || /^.+\\n=+\\s*$/m.test(text)\n || /^.+\\n-{2,}\\s*$/m.test(text)\n || /^---\\s*\\n(?:[\\s\\S]*?\\n)?(?:---|\\.\\.\\.)\\s*(?:\\n|$)/.test(text)\n || /^\\|.+\\|[ \\t]*\\n\\|[ \\t:|-]+\\|/m.test(text);\n}\n\n// Blockquote line: optional up-to-3 leading spaces, '>', optional single space, rest of line.\nconst BQ_RE = /^ {0,3}>( ?)(.*)$/;\n// Horizontal rule: 3+ of the same character (-, * or _), optionally space-separated.\nconst HR_RE = /^ {0,3}([-*_])( *\\1){2,}\\s*$/;\n// Hard-break marker — placed between paragraph lines that end in a\n// CommonMark hard-break (trailing 2+ spaces or a trailing backslash),\n// restored to <br> after _inline() runs. Distinct from _inline()'s own MARK.\nconst HARD_BREAK = String.fromCharCode(1);\n\n/**\n * Converts a Markdown string to an HTML string.\n * @param {string} text\n * @returns {string}\n */\nexport function markdownToHTML(text) {\n let lines = text.replaceAll('\\r\\n', '\\n').replaceAll('\\r', '\\n').split('\\n');\n lines = _stripFrontmatter(lines);\n const refs = _extractReferenceDefinitions(lines);\n lines = refs.clean;\n _linkDefs = refs.linkDefs;\n _footnoteIds = refs.footnoteIds;\n return _parseBlocks(lines);\n}\n\n/**\n * Parses a line array into block-level HTML. Called recursively for content\n * nested inside a blockquote so nested quotes and block content (lists,\n * headings, etc.) inside `>` are parsed the same as top-level content.\n * @param {string[]} lines\n * @returns {string}\n */\nfunction _parseBlocks(lines) {\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 = /^```(\\S*)$/.exec(line);\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 // ---- Setext headings (Title\\n=== or Title\\n---) -------------------------\n if (line.trim() && !HR_RE.test(line) && !/^#{1,6} /.test(line) && i + 1 < lines.length) {\n if (/^=+\\s*$/.test(lines[i + 1])) {\n out.push(`<h1>${_inline(line.trim())}</h1>`);\n i += 2;\n continue;\n }\n if (/^-{2,}\\s*$/.test(lines[i + 1])) {\n out.push(`<h2>${_inline(line.trim())}</h2>`);\n i += 2;\n continue;\n }\n }\n\n // ---- Horizontal rule --- / *** / ___ / - - - / * * * ----------------------\n if (HR_RE.test(line)) {\n out.push('<hr>');\n i++;\n continue;\n }\n\n // ---- ATX Headings # – ###### -------------------------------------------\n const hMatch = /^(#{1,6})\\s+(.+)$/.exec(line);\n if (hMatch) {\n const level = hMatch[1].length;\n // Strip an optional closing sequence of #'s (e.g. \"## Heading ##\"),\n // only when preceded by whitespace — \"Heading#\" (no space) is untouched.\n const content = hMatch[2].replace(/(?:^|\\s)#+\\s*$/, '');\n out.push(`<h${level}>${_inline(content)}</h${level}>`);\n i++;\n continue;\n }\n\n // ---- Blockquote > text --------------------------------------------------\n if (BQ_RE.test(line)) {\n const bqLines = [];\n while (i < lines.length && BQ_RE.test(lines[i])) {\n bqLines.push(BQ_RE.exec(lines[i])[2]);\n i++;\n }\n out.push(`<blockquote>${_parseBlocks(bqLines)}</blockquote>`);\n continue;\n }\n\n // ---- Checklist or Unordered list - / * / + item ----------------------\n if (/^[-*+] /.test(line)) {\n const { html: listHtml, endIdx } = _parseListBlock(lines, i);\n out.push(listHtml); i = endIdx; continue;\n }\n\n // ---- Ordered list 1. item ----------------------------------------------\n if (/^\\d+\\. /.test(line)) {\n const { html: listHtml, endIdx } = _parseListBlock(lines, i);\n out.push(listHtml); i = endIdx; 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 const alignments = _parseTableRow(lines[i + 1]).map((c) => {\n if (c.startsWith(':') && c.endsWith(':')) return 'center';\n if (c.endsWith(':')) return 'right';\n if (c.startsWith(':')) return 'left';\n return null;\n });\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 _cell = (tag, content, align) => {\n const s = align ? ` style=\"text-align:${align}\"` : '';\n return `<${tag}${s}>${_inline(content)}</${tag}>`;\n };\n const thCells = headerCells.map((c, idx) => _cell('th', c, alignments[idx])).join('');\n const thead = `<thead><tr>${thCells}</tr></thead>`;\n const renderRow = (row) => `<tr>${row.map((c, idx) => _cell('td', c, alignments[idx])).join('')}</tr>`;\n const tbody = bodyRows.length ? `<tbody>${bodyRows.map(renderRow).join('')}</tbody>` : '';\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+\\. |```)/.test(lines[i]) &&\n !BQ_RE.test(lines[i]) &&\n !HR_RE.test(lines[i]) &&\n !/^\\|.+\\|/.test(lines[i]) &&\n !(i + 1 < lines.length && /^=+\\s*$/.test(lines[i + 1])) &&\n !(i + 1 < lines.length && /^-{2,}\\s*$/.test(lines[i + 1]))\n ) {\n paraLines.push(lines[i]);\n i++;\n }\n if (paraLines.length) {\n out.push(`<p>${_inline(_joinParagraphLines(paraLines)).replaceAll(HARD_BREAK, '<br>')}</p>`);\n }\n }\n\n return out.join('');\n}\n\n// ---------------------------------------------------------------------------\n// Inline formatting\n// ---------------------------------------------------------------------------\n\n/** Reference-link and footnote definitions collected per markdownToHTML() call. */\nlet _linkDefs = new Map();\nlet _footnoteIds = new Set();\n\n/**\n * Strips a leading YAML frontmatter block (--- ... --- or --- ... ...) from\n * the line array, only when it is the very first line and the enclosed body\n * looks like YAML (key: value / list items / indented continuations) — this\n * disambiguates real frontmatter from a horizontal rule followed by prose.\n * @param {string[]} lines\n * @returns {string[]}\n */\nfunction _stripFrontmatter(lines) {\n if ((lines[0] || '').trim() !== '---') return lines;\n let closeIdx = -1;\n for (let j = 1; j < lines.length; j++) {\n const t = lines[j].trim();\n if (t === '---' || t === '...') { closeIdx = j; break; }\n }\n if (closeIdx === -1) return lines;\n\n const body = lines.slice(1, closeIdx);\n const looksLikeYAML = body.every((l) =>\n l.trim() === '' ||\n /^[ \\t]*[\\w$.-]+\\s*:(\\s|$)/.test(l) ||\n /^[ \\t]*-\\s+\\S/.test(l) ||\n /^[ \\t]+\\S/.test(l));\n if (!looksLikeYAML) return lines;\n\n let start = closeIdx + 1;\n if (lines[start] !== undefined && lines[start].trim() === '') start++;\n return lines.slice(start);\n}\n\n/**\n * Extracts GFM reference-link definitions (`[ref]: url \"title\"`) and footnote\n * definitions (`[^id]: text`) from the line array, skipping fenced code\n * regions. Returns the definition-free line array plus lookup maps.\n * @param {string[]} lines\n * @returns {{ clean: string[], linkDefs: Map<string, {href: string, title?: string}>, footnoteIds: Set<string> }}\n */\nfunction _extractReferenceDefinitions(lines) {\n const linkDefs = new Map();\n const footnoteIds = new Set();\n const clean = [];\n let inFence = false;\n const linkDefRe = /^\\[([^\\]]+)\\]:\\s*(\\S+)(?:\\s+\"([^\"]*)\")?\\s*$/;\n const footnoteDefRe = /^\\[\\^([^\\]]+)\\]:\\s*(.+)$/;\n\n for (const line of lines) {\n if (/^```/.test(line)) { inFence = !inFence; clean.push(line); continue; }\n if (!inFence) {\n const fm = footnoteDefRe.exec(line);\n if (fm) { footnoteIds.add(fm[1]); continue; }\n const lm = linkDefRe.exec(line);\n if (lm) { linkDefs.set(lm[1].trim().toLowerCase(), { href: lm[2], title: lm[3] }); continue; }\n }\n clean.push(line);\n }\n return { clean, linkDefs, footnoteIds };\n}\n\n/**\n * Joins a paragraph's source lines into one string, converting CommonMark\n * hard-break markers (a trailing backslash, or 2+ trailing spaces) on all\n * but the last line into a HARD_BREAK placeholder instead of a plain space.\n * @param {string[]} paraLines\n * @returns {string}\n */\nfunction _joinParagraphLines(paraLines) {\n let joined = '';\n for (let idx = 0; idx < paraLines.length; idx++) {\n const isLast = idx === paraLines.length - 1;\n const ln = paraLines[idx];\n if (!isLast && /\\\\$/.test(ln)) { joined += ln.replace(/\\\\$/, '') + HARD_BREAK; continue; }\n if (!isLast && / {2,}$/.test(ln)) { joined += ln.replace(/ {2,}$/, '') + HARD_BREAK; continue; }\n joined += ln + (isLast ? '' : ' ');\n }\n return joined;\n}\n\n/**\n * Splits a GFM table row string into trimmed cell strings, treating an\n * escaped pipe (`\\|`) as a literal character rather than a cell separator.\n * '| a | b | c |' → ['a', 'b', 'c']; '| a\\|b | c |' → ['a|b', 'c']\n * @param {string} row\n * @returns {string[]}\n */\nfunction _parseTableRow(row) {\n const trimmed = row.replace(/^\\|/, '').replace(/\\|$/, '');\n const cells = [];\n let cur = '';\n for (let i = 0; i < trimmed.length; i++) {\n if (trimmed[i] === '\\\\' && trimmed[i + 1] === '|') { cur += '|'; i++; continue; }\n if (trimmed[i] === '|') { cells.push(cur); cur = ''; continue; }\n cur += trimmed[i];\n }\n cells.push(cur);\n return cells.map((c) => c.trim());\n}\n\nfunction _parseListBlock(lines, startIdx) {\n const baseIndent = (lines[startIdx].match(/^(\\s*)/)[1]).length;\n const isOL = /^\\s*\\d+\\. /.test(lines[startIdx]);\n const items = [];\n let firstIsCB = null;\n let loose = false;\n let pendingBlank = false;\n let i = startIdx;\n\n while (i < lines.length) {\n const line = lines[i];\n\n if (line.trim() === '') {\n // A blank line only ends the list if what follows isn't a continuation\n // of it (another item at the same marker/indent, or indented text\n // belonging to the current item) — otherwise it marks a \"loose\" list.\n const next = lines[i + 1];\n const nextIndent = next !== undefined ? (next.match(/^(\\s*)/)[1]).length : -1;\n const nextIsSameItem = next !== undefined &&\n /^\\s*(?:[-*+]|\\d+\\.) /.test(next) &&\n (/^\\s*\\d+\\. /.test(next) === isOL) &&\n nextIndent === baseIndent;\n const nextIsContinuation = next !== undefined && next.trim() !== '' && nextIndent > baseIndent;\n if (!items.length || (!nextIsSameItem && !nextIsContinuation)) break;\n loose = true;\n pendingBlank = true;\n i++;\n continue;\n }\n\n const indent = (line.match(/^(\\s*)/)[1]).length;\n if (indent < baseIndent) break;\n\n if (indent === baseIndent) {\n if (!/^\\s*(?:[-*+]|\\d+\\.) /.test(line)) break;\n if (/^\\s*\\d+\\. /.test(line) !== isOL) break;\n const raw = isOL ? line.replace(/^\\s*\\d+\\. /, '') : line.replace(/^\\s*[-*+] /, '');\n // Checklists are intentionally UL-only: sanitise.js's checkbox guard,\n // the injected checklist CSS, and every checklist-toggle command are\n // all hardcoded to `ul.an-checklist` with no `ol` equivalent, so an\n // ordered-list checkbox would be stripped by the sanitiser and get no\n // styling even if parsed here — \"1. [ ] item\" intentionally stays plain.\n const isCB = !isOL && /^\\[[ xX]\\]\\s+/.test(raw);\n if (firstIsCB === null) firstIsCB = isCB;\n if (isCB !== firstIsCB) break;\n const checked = isCB && raw[1].toLowerCase() === 'x';\n const text = isCB ? raw.replace(/^\\[[ xX]\\]\\s+/, '') : raw;\n items.push({ paras: [text], isCB, checked, sub: '' });\n pendingBlank = false;\n i++;\n } else {\n if (!items.length) { i++; continue; }\n if (/^\\s*(?:[-*+]|\\d+\\.) /.test(line)) {\n const nested = _parseListBlock(lines, i);\n items[items.length - 1].sub += nested.html;\n i = nested.endIdx;\n pendingBlank = false;\n } else if (pendingBlank) {\n items[items.length - 1].paras.push(line.trim());\n pendingBlank = false;\n i++;\n } else {\n const paras = items[items.length - 1].paras;\n paras[paras.length - 1] += ' ' + line.trim();\n i++;\n }\n }\n }\n\n const hasCB = !isOL && (firstIsCB === true);\n const startMatch = isOL ? /^\\s*(\\d+)\\. /.exec(lines[startIdx]) : null;\n const startNum = startMatch ? Number.parseInt(startMatch[1], 10) : 1;\n const open = isOL\n ? (startNum !== 1 ? `<ol start=\"${startNum}\">` : '<ol>')\n : (hasCB ? '<ul class=\"an-checklist\">' : '<ul>');\n const close = isOL ? '</ol>' : '</ul>';\n const liHTML = items.map(({ paras, isCB, checked, sub }) => {\n const cbHTML = isCB\n ? `<input type=\"checkbox\" contenteditable=\"false\"${checked ? ' checked' : ''}>`\n : '';\n const body = loose\n ? paras.map((p, idx) => `<p>${idx === 0 ? cbHTML : ''}${_inline(p)}</p>`).join('')\n : `${cbHTML}${_inline(paras[0])}`;\n return `<li>${body}${sub}</li>`;\n }).join('');\n return { html: `${open}${liHTML}${close}`, endIdx: i };\n}\n\n// Backslash-escapable inline punctuation (CommonMark-ish, narrowed to the\n// syntax characters this converter actually uses).\nconst ESCAPABLE_RE = /\\\\([*_`#[\\]()>\\\\~|])/g;\n// Placeholder marker for escaped literals — a NUL character can't appear in\n// real markdown text, so it's safe as a delimiter. Built at runtime (not\n// written as a literal escape) to avoid embedding a raw NUL byte in this file.\nconst MARK = String.fromCharCode(0);\n\n/**\n * Step 0 of _inline(): replaces backslash-escaped punctuation with inert\n * placeholders so later syntax regexes can't match them.\n * @param {string} text\n * @returns {{ text: string, literals: string[] }}\n */\nfunction _extractBackslashEscapes(text) {\n const literals = [];\n const replaced = text.replace(ESCAPABLE_RE, (_, ch) => {\n literals.push(ch);\n return `${MARK}${literals.length - 1}${MARK}`;\n });\n return { text: replaced, literals };\n}\n\n/**\n * Restores placeholders from _extractBackslashEscapes(), HTML-escaping each\n * literal since it's inserted directly into the output.\n * @param {string} text\n * @param {string[]} literals\n * @returns {string}\n */\nfunction _restoreBackslashEscapes(text, literals) {\n return text.replace(new RegExp(`${MARK}(\\\\d+)${MARK}`, 'g'), (_, idx) => _esc(literals[Number(idx)]));\n}\n\n/**\n * Resolves images, inline links, GFM reference-style links (explicit,\n * shortcut, and bare/implicit forms), and footnote markers. Must run on text\n * already passed through _esc() — see _inline()'s Step 1 comment.\n * @param {string} text\n * @returns {string}\n */\nfunction _resolveLinksAndFootnotes(text) {\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, (_, alt, src) =>\n `<img src=\"${_escAttrQuotes(src)}\" alt=\"${_escAttrQuotes(alt)}\" class=\"an-image\">`);\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, label, href) =>\n `<a href=\"${_escAttrQuotes(href)}\">${label}</a>`);\n text = text.replace(/\\[([^\\]]+)\\]\\[([^\\]]*)\\]/g, (m, label, ref) => {\n const def = _linkDefs.get(_unescAmpLtGt(ref || label).trim().toLowerCase());\n if (!def) return m;\n const titleAttr = def.title ? ` title=\"${_escAttr(def.title)}\"` : '';\n return `<a href=\"${_escAttr(def.href)}\"${titleAttr}>${label}</a>`;\n });\n text = text.replace(/\\[([^\\]]+)\\]/g, (m, label) => {\n const def = _linkDefs.get(_unescAmpLtGt(label).trim().toLowerCase());\n if (!def) return m;\n const titleAttr = def.title ? ` title=\"${_escAttr(def.title)}\"` : '';\n return `<a href=\"${_escAttr(def.href)}\"${titleAttr}>${label}</a>`;\n });\n text = text.replace(/\\[\\^([^\\]]+)\\]/g, (m, id) => (_footnoteIds.has(_unescAmpLtGt(id)) ? `<sup>[${id}]</sup>` : m));\n return text;\n}\n\n/**\n * Converts angle-bracket (`<https://...>`) and bare (`https://...`)\n * autolinks. Runs after _resolveLinksAndFootnotes() so an already-linked URL\n * isn't reprocessed, and on already-_esc()'d text (see _inline()).\n * @param {string} text\n * @returns {string}\n */\nfunction _applyAutolinks(text) {\n text = text.replace(/&lt;(https?:\\/\\/[^\\s&]+?)&gt;/g, (_, url) => `<a href=\"${_escAttrQuotes(url)}\">${url}</a>`);\n text = text.replace(/(^|[\\s(])(https?:\\/\\/[^\\s()]+)/g, (m, pre, rawUrl) => {\n const trail = /[.,;:!?)]+$/.exec(rawUrl);\n const url = trail ? rawUrl.slice(0, -trail[0].length) : rawUrl;\n if (!url) return m;\n const suffix = trail ? trail[0] : '';\n return `${pre}<a href=\"${_escAttrQuotes(url)}\">${url}</a>${suffix}`;\n });\n return text;\n}\n\n/**\n * Applies bold/italic/bold-italic (asterisk and underscore forms — underscore\n * requires a non-word-character boundary per CommonMark), strikethrough, and\n * inline code.\n * @param {string} text\n * @returns {string}\n */\nfunction _applyEmphasisAndCode(text) {\n text = text.replace(/\\*{3}([^*\\n]+?)\\*{3}/g, (_, c) => `<strong><em>${c}</em></strong>`);\n text = text.replace(/(?<!\\w)_{3}([^_\\n]+?)_{3}(?!\\w)/g, (_, c) => `<strong><em>${c}</em></strong>`);\n text = text.replace(/\\*{2}([^*\\n]+?)\\*{2}/g, (_, c) => `<strong>${c}</strong>`);\n text = text.replace(/(?<!\\w)_{2}([^_\\n]+?)_{2}(?!\\w)/g, (_, c) => `<strong>${c}</strong>`);\n text = text.replace(/\\*([^*\\n]+?)\\*/g, (_, c) => `<em>${c}</em>`);\n text = text.replace(/(?<!\\w)_([^_\\n]+?)_(?!\\w)/g, (_, c) => `<em>${c}</em>`);\n text = text.replace(/~~([^~\\n]+?)~~/g, (_, c) => `<del>${c}</del>`);\n // Double-backtick code spans first (tolerates a single literal ` inside),\n // then single-backtick spans.\n text = text.replace(/``([\\s\\S]*?)``/g, (_, c) => `<code>${c}</code>`);\n text = text.replace(/`([^`]+)`/g, (_, c) => `<code>${c}</code>`);\n return text;\n}\n\nfunction _inline(text) {\n // Step 0: backslash escapes (\\* \\_ \\` \\# \\[ \\] \\( \\) \\> \\\\ \\~ \\|) — replaced\n // with inert placeholders before any syntax regex below can match them, so\n // e.g. \\*not bold\\* never gets treated as emphasis. Restored at the end.\n const { text: withoutEscapes, literals } = _extractBackslashEscapes(text);\n\n // Step 1: escape raw &/</> in the plain-text parts of the string exactly\n // once, up front — none of these are markdown-syntax characters used below,\n // so this doesn't interfere with matching. Capture-group content in the\n // steps below is therefore ALREADY escaped and must NOT be re-escaped;\n // attribute values captured from `text` only need quotes escaped\n // (_escAttrQuotes), since & < > are already entities. Values that come from\n // _linkDefs (sourced from the raw, unescaped line array) still need the\n // full _escAttr/_esc treatment.\n let result = _esc(withoutEscapes);\n\n result = _resolveLinksAndFootnotes(result);\n result = _applyAutolinks(result);\n result = _applyEmphasisAndCode(result);\n\n return _restoreBackslashEscapes(result, literals);\n}\n\nfunction _esc(v) {\n return String(v)\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\n}\n\nfunction _escAttr(v) {\n return String(v)\n .replaceAll('&', '&amp;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\n}\n\n/** Escapes only quote characters — for attribute values already run through _esc(). */\nfunction _escAttrQuotes(v) {\n return String(v).replaceAll('\"', '&quot;').replaceAll(\"'\", '&#39;');\n}\n\n/** Reverses _esc()'s &amp;/&lt;/&gt; substitutions, for matching against un-escaped _linkDefs/_footnoteIds keys. */\nfunction _unescAmpLtGt(v) {\n return String(v).replaceAll('&lt;', '<').replaceAll('&gt;', '>').replaceAll('&amp;', '&');\n}\n","/**\n * detectLang.js — Heuristic programming-language detection for code snippets.\n *\n * Returns a Prism.js language identifier or null when no language can be\n * determined with reasonable confidence.\n *\n * Detection order (conflicts in parentheses):\n * TypeScript → Rust → PHP → Java → Kotlin → Swift → Go\n * → JavaScript → HTML → CSS → JSON → SQL → Python → Ruby\n * → Bash → C++ → C# → C → XML\n *\n * @param {string} code\n * @returns {string|null}\n */\nexport function detectLang(code) {\n if (!code?.trim()) return null;\n const s = code.trim();\n\n // ── TypeScript ─────────────────────────────────────────────────────────────\n // Must be first — TS is a JS superset; its markers are specific.\n if (/(:\\s*(string|number|boolean|void|never|any|unknown)\\b|interface\\s+\\w+\\s*\\{|type\\s+\\w+\\s*[=<(]|<\\w+>\\s*[;,)]|readonly\\s+\\w|enum\\s+\\w+\\s*\\{|\\?\\s*:\\s*\\w|as\\s+\\w+\\s*[;,)\\]])/.test(s)) return 'typescript';\n\n // ── Rust ────────────────────────────────────────────────────────────────────\n // Before JavaScript — both have `let`. `!` macros and `pub fn` are unique.\n if (/\\bprintln!\\s*\\(|\\bprint!\\s*\\(|\\bfn\\s+\\w+\\s*(<[^>]*>)?\\s*\\(|\\blet\\s+mut\\s|\\bpub\\s+fn\\s|\\buse\\s+std::|\\bimpl\\s+\\w+|\\bOption<|\\bResult<\\w+/.test(s)) return 'rust';\n\n // ── PHP ─────────────────────────────────────────────────────────────────────\n // Before Bash — both have `echo`. `<?php` and `$var` are unique to PHP.\n if (/(<\\?php\\b|<\\?=|\\becho\\s+.*\\$\\w|\\$this->|\\$\\w+\\s*=\\s*\\w|\\bforeach\\s*\\(\\s*\\$|Illuminate\\\\)/.test(s)) return 'php';\n\n // ── Java ────────────────────────────────────────────────────────────────────\n // Before Kotlin — `System.out.println()` would otherwise match Kotlin's\n // `println\\s*\\(` pattern.\n if (/\\bpublic\\s+(class|static|void|int|String)\\s+\\w|System\\.out\\.(print|println)\\s*\\(|@(Override|Autowired|Component|Service|Controller)\\b|import\\s+java\\.(util|io|lang|net)\\.|throws\\s+\\w+Exception/.test(s)) return 'java';\n\n // ── Kotlin ──────────────────────────────────────────────────────────────────\n // Kotlin uses `val` (immutable) unlike Swift/JS which use `let`.\n // `fun`, `data class`, `companion object`, `println()` are Kotlin-specific.\n if (/\\bfun\\s+\\w+\\s*\\(|\\bdata\\s+class\\s+\\w+|\\bcompanion\\s+object\\b|\\bval\\s+\\w+\\s*:\\s*\\w|\\bprintln\\s*\\(/.test(s)) return 'kotlin';\n\n // ── Swift ───────────────────────────────────────────────────────────────────\n // Swift uses `let` for constants (Kotlin uses `val`). `guard let`, `protocol`,\n // `extension`, `func ... -> ReturnType`, and `let x: UppercaseType` are signals.\n if (/\\bguard\\s+(let|var)\\b|\\bprotocol\\s+\\w+\\s*\\{|\\bextension\\s+\\w+|\\bfunc\\s+\\w+[^(]*\\([^)]*\\)\\s*->\\s*\\w|\\blet\\s+\\w+\\s*:\\s*[A-Z]\\w*|\\bSwiftUI\\b/.test(s)) return 'swift';\n\n // ── Go ──────────────────────────────────────────────────────────────────────\n // `package`, `:=` short assignment, `fmt.Print*`, `chan`, `goroutine`.\n if (/\\bpackage\\s+\\w+\\b|\\bfmt\\.(Print|Println|Sprintf|Errorf|Fprintf)\\s*\\(|:=\\s*\\w|\\bgoroutine\\b|\\bchan\\s+\\w|\\bgo\\s+func\\b/.test(s)) return 'go';\n\n // ── JavaScript ──────────────────────────────────────────────────────────────\n // Before HTML to handle JSX (`<div/>` would otherwise trigger HTML).\n // `var\\s+\\w+\\s*=` (not just `var\\s+\\w`) to avoid matching Swift `var x: Int`.\n if (/\\b(const\\s+\\w|let\\s+\\w+\\s*=|var\\s+\\w+\\s*=|function\\s+\\w|\\=>\\s*[{(]|import\\s+.*\\bfrom\\b\\s*['\"]|require\\s*\\(|console\\.(log|error|warn|info)|document\\.\\w|window\\.\\w|async\\s+function|\\bPromise\\b|React\\.|useState\\s*\\(|\\.then\\s*\\()/.test(s)) return 'javascript';\n\n // ── HTML ────────────────────────────────────────────────────────────────────\n if (/^<!DOCTYPE html/i.test(s) || /<(html|head|body|div|section|article|nav|p|a|img|ul|ol|li|table|form|input|button|script|style)\\b[^>]*>/i.test(s)) return 'html';\n\n // ── SCSS ─────────────────────────────────────────────────────────────────────\n // Before CSS — SCSS is a superset. Unique markers: `//` line comments,\n // `&` nesting, `$variable`, `@mixin/@include/@extend`, `#{interpolation}`.\n if (/(^|\\n)\\s*(\\/\\/\\s+\\S|&[:.[\\w]|\\$\\w+\\s*:|@(mixin|include|extend|each|if|for|use|forward)\\b|#\\{)/.test(s) && /[\\w#.*&[\\]:(),>+~ -]+\\s*\\{/.test(s)) return 'scss';\n\n // ── CSS ──────────────────────────────────────────────────────────────────────\n if (/(^|\\n)\\s*[\\w#.*:[\\]&, +-]+\\s*\\{[^}]*[\\w-]+\\s*:[^{}:;]+[;}\\n]/m.test(s) && !/<\\w|function\\s|def\\s|:\\s*(string|number)/.test(s)) return 'css';\n\n // ── JSON ────────────────────────────────────────────────────────────────────\n if (/^\\s*[{[]/.test(s) && /\"\\w[\\w\\s-]*\"\\s*:/.test(s) && !/\\bfunction\\b|\\bdef\\b/.test(s)) return 'json';\n\n // ── SQL ─────────────────────────────────────────────────────────────────────\n if (/(^|\\n)\\s*(SELECT\\s|INSERT\\s+INTO|UPDATE\\s+\\w|DELETE\\s+FROM|CREATE\\s+(TABLE|DATABASE|INDEX|VIEW)|DROP\\s+(TABLE|DATABASE)|ALTER\\s+TABLE|WITH\\s+\\w+\\s+AS\\s*\\()/im.test(s)) return 'sql';\n\n // ── Python ──────────────────────────────────────────────────────────────────\n // `def` requires trailing `:` (Python rule); `class` checked at line start.\n if (/\\bdef\\s+\\w+\\s*\\([^)]*\\)\\s*:|(^|\\n)\\s*class\\s+\\w+.*:\\s*$|(^|\\n)\\s*import\\s+\\w|(^|\\n)\\s*from\\s+\\w+\\s+import\\s+|\\bprint\\s*\\(|if\\s+__name__\\s*==\\s*['\"]__main__['\"]/m.test(s)) return 'python';\n\n // ── Ruby ────────────────────────────────────────────────────────────────────\n // `.each do |x|`, `attr_*`, `puts` with value, multi-line `def...end`.\n if (/\\bputs\\s+\\S|\\battr_(accessor|reader|writer)\\s|\\.each\\s+do\\s*\\|\\w+\\s*\\||\\bdo\\s*\\|\\w+\\s*\\|.*\\bend\\b|\\bdef\\s+\\w+[^:]*\\n[\\s\\S]*?\\bend\\b/.test(s)) return 'ruby';\n\n // ── Bash / Shell ─────────────────────────────────────────────────────────────\n if (/^#!.*\\/(ba|z|da|fi|k)?sh\\b/m.test(s) || /\\b(echo\\s+[\"']|grep\\s+|awk\\s+|sed\\s+['\"\\\\/-]|chmod\\s+|sudo\\s+|apt(-get)?\\s+install|brew\\s+install|npm\\s+(install|run|start|build)|pip\\s+(install|3\\s)|docker\\s+(run|build|compose)|kubectl\\s+|git\\s+(clone|add|commit|push|pull|checkout))\\b/.test(s)) return 'bash';\n\n // ── C++ ─────────────────────────────────────────────────────────────────────\n // Before C and C# — `cout<<`, `using namespace std`, `std::`, `template<>`.\n if (/\\bcout\\s*<<|\\bcin\\s*>>|using\\s+namespace\\s+std\\b|std::\\w|\\btemplate\\s*<\\w|\\b#include\\s*<(iostream|vector|map|set|algorithm|string|memory)>/.test(s)) return 'cpp';\n\n // ── C# ──────────────────────────────────────────────────────────────────────\n // After C++ to avoid matching C++'s `using namespace std`.\n if (/\\busing\\s+System\\b|Console\\.(Write|WriteLine)\\s*\\(|\\bget;\\s*set;|\\basync\\s+Task[<\\s]|IEnumerable<|\\bLINQ\\b|\\.Select\\s*\\(|\\.Where\\s*\\(/.test(s)) return 'csharp';\n\n // ── C ───────────────────────────────────────────────────────────────────────\n if (/\\b#include\\s*<(stdio|stdlib|string|math|time|ctype)\\.h>|\\bprintf\\s*\\(|\\bscanf\\s*\\(|int\\s+main\\s*\\(\\s*(void|int\\s+argc)|\\bmalloc\\s*\\(|\\bfree\\s*\\(/.test(s) && !/namespace|cout|cin|std::/.test(s)) return 'c';\n\n // ── XML ─────────────────────────────────────────────────────────────────────\n if (/^<\\?xml\\s/i.test(s) || /xmlns:|<\\/[\\w:]+>/.test(s)) return 'xml';\n\n return null;\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';\nimport { detectLang } from '../core/detectLang.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(\n editable,\n this.options.historyLimit || 100,\n this.options.historyMaxBytes || 10 * 1024 * 1024,\n );\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 = globalThis.getSelection();\n if (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 = globalThis.getSelection();\n if (!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 scEl = /** @type {Element} */ (sc);\n const li = scEl.matches('.an-checklist li') ? scEl : 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?.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 = /** @type {Element} */ (e.target);\n if (target && (target.nodeName === 'IFRAME' ||\n 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 = globalThis.getSelection();\n if (!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) {\n const el = /** @type {Element} */ (node);\n if (el.closest('sup')) _compositionSupSub = 'superscript';\n else if (el.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 = globalThis.getSelection();\n if (!sel?.rangeCount) return;\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n const el = /** @type {Element} */ (node);\n const inContext = tag === 'superscript' ? el?.closest('sup') : el?.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.replaceAll('\\n', '').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 // Ensure the editable always ends with a paragraph so the user can click\n // and type after block elements that trap the cursor (pre, table, etc.).\n this._ensureTrailingParagraph();\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.remove();\n }\n });\n }\n\n /**\n * Ensures the editable always ends with a plain paragraph so the cursor can\n * be placed after block elements that do not naturally allow it\n * (pre, blockquote, table, figure, ul, ol, hr).\n * Without this, clicking below the last such element does nothing.\n */\n _ensureTrailingParagraph() {\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n const last = editable.lastElementChild;\n if (!last) return;\n const TRAPPING = new Set(['PRE', 'BLOCKQUOTE', 'TABLE', 'FIGURE', 'UL', 'OL', 'HR']);\n if (TRAPPING.has(last.nodeName)) {\n const p = document.createElement('p');\n p.innerHTML = '<br>';\n editable.appendChild(p);\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.replaceAll('\\u200B', '');\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 .replaceAll('\\u00a0', '');\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 this._flushPendingSnapshot();\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 this._flushPendingSnapshot();\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 /** Records a debounced change before an immediate undo/redo command. */\n _flushPendingSnapshot() {\n if (this._snapshotTimer === null) return;\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n this._history?.recordUndo();\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 getUndoCount() {\n return this._history ? this._history.getUndoCount() : 0;\n }\n\n getRedoCount() {\n return this._history ? this._history.getRedoCount() : 0;\n }\n\n getSelectionBookmark() {\n return this._history?._serializeSelection() ?? null;\n }\n\n restoreSelectionBookmark(bookmark) {\n if (!bookmark || !this._history) return false;\n this._history._restoreSelection(bookmark);\n return true;\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', 'pre'\n */\n formatBlock(tagName) {\n Style.formatBlock(tagName);\n\n // Auto-detect the programming language when the user formats a code block.\n // Only runs when converting TO <pre> and the block has no language yet.\n if (tagName === 'pre') {\n const sel = globalThis.getSelection();\n if (sel?.rangeCount > 0) {\n const container = sel.getRangeAt(0).commonAncestorContainer;\n const pre = /** @type {Element|null} */ (\n container.nodeType === 1\n ? /** @type {Element} */ (container).closest('pre')\n : (/** @type {Element|null} */ (container.parentElement))?.closest('pre')\n );\n if (pre && !/** @type {HTMLElement} */ (pre).dataset.language) {\n const code = pre.textContent || '';\n const lang = detectLang(code);\n if (lang) {\n this.context.invoke('codeTooltip.applyLanguage', pre, lang);\n return; // applyLanguage already calls afterCommand internally\n }\n }\n }\n }\n\n this.afterCommand();\n }\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 = globalThis.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 Style.execCommand('createLink', safeUrl);\n if (openInNewTab) {\n const link = this._getClosestAnchor();\n if (link) {\n /** @type {Element} */ (link).setAttribute('target', '_blank');\n /** @type {Element} */ (link).setAttribute('rel', 'noopener noreferrer');\n }\n }\n } else {\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 }\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 = globalThis.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 .replaceAll('&', '&amp;')\n .replaceAll('\"', '&quot;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\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';\nimport { getButton } from './Buttons.js';\n\n/** Resolve a toolbar item: string → registry lookup, object → pass-through. */\nconst _resolveBtn = (item) => (typeof item === 'string') ? getButton(item) : item;\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 /** @type {number|null} rAF handle for debounced refresh */\n this._refreshRaf = null;\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(\n (this.options.toolbar || []).flat()\n .map(_resolveBtn).filter(Boolean).map((b) => [b.name, b]),\n );\n return this;\n }\n\n destroy() {\n if (this._refreshRaf) cancelAnimationFrame(this._refreshRaf);\n this._refreshRaf = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this.el?.parentNode) {\n this.el.remove();\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((item) => {\n const btnDef = _resolveBtn(item);\n if (!btnDef) {\n console.warn(`[AutumnNote] Toolbar: button \"${item}\" not found in registry. Skipped.`);\n return;\n }\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.dataset.row;\n const c = +cell.dataset.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 const rect = btn.getBoundingClientRect();\n\n // Measure popup dimensions while invisible so we can set the correct\n // position before the browser paints (matches the color-picker pattern).\n popup.style.visibility = 'hidden';\n popup.style.display = 'block';\n const pw = popup.offsetWidth;\n const ph = popup.offsetHeight;\n\n let left = rect.left;\n let top = rect.bottom + 4;\n if (left + pw > globalThis.innerWidth - 8) left = Math.max(8, globalThis.innerWidth - pw - 8);\n if (top + ph > globalThis.innerHeight - 8) top = rect.top - ph - 4;\n\n popup.style.left = `${left}px`;\n popup.style.top = `${top}px`;\n popup.style.visibility = '';\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 = /** @type {HTMLElement|null} */ (/** @type {Element} */ (e.target)?.closest('.an-table-cell'));\n if (!cell) return;\n setHighlight(+cell.dataset.row, +cell.dataset.col);\n });\n\n const d3 = on(grid, 'mouseleave', () => setHighlight(0, 0));\n\n const d4 = on(grid, 'click', (e) => {\n const cell = /** @type {HTMLElement|null} */ (/** @type {Element} */ (e.target)?.closest('.an-table-cell'));\n if (!cell) return;\n const rows = +cell.dataset.row;\n const cols = +cell.dataset.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 // Append popup to body so position:fixed is truly viewport-relative,\n // unaffected by any ancestor transform / filter (same pattern as color picker).\n this._disposers.push(d1, d2, d3, d4, d5, () => {\n if (popup.parentNode) popup.remove();\n });\n\n wrap.appendChild(btn);\n document.body.appendChild(popup);\n return /** @type {HTMLDivElement} */ (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 = /** @type {HTMLInputElement} */ (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 = globalThis.getSelection();\n savedRange = sel?.rangeCount ? sel.getRangeAt(0).cloneRange() : null;\n };\n\n const restoreSelection = () => {\n if (!savedRange) return;\n try {\n const sel = globalThis.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(savedRange);\n } catch (_) {\n void _; // range may be stale 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 > globalThis.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 = /** @type {Element} */ (e.target)?.closest('.an-color-swatch');\n if (sw) applyColor(/** @type {HTMLElement} */ (sw).dataset.color);\n });\n\n const d4 = on(colorInput, 'change', (e) => {\n applyColor(/** @type {HTMLInputElement} */ (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(/** @type {Node} */ (e.target)) && !popup.contains(/** @type {Node} */ (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 globalThis.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 () => globalThis.removeEventListener('resize', onScrollResize),\n // Remove popup from body on editor destroy\n () => { if (popup.parentNode) popup.remove(); },\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 /** @type {HTMLDivElement} */ (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 let label;\n if (typeof item !== 'object') {\n label = item;\n } else if (def.name === 'paragraphStyle') {\n label = this.context.locale.toolbar.paragraphItems?.[item.value] || item.label;\n } else {\n label = item.label;\n }\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 = globalThis.getSelection();\n _savedRange = 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 = globalThis.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(_savedRange); }\n } catch (_) { void _; /* 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 /** @type {HTMLSelectElement} */ (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 if (_SVG_MAP.has(btnDef.icon)) {\n // FontAwesome absent: use SVG fallback when available\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 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 /** @type {HTMLButtonElement} */ (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) => /** @type {HTMLLinkElement} */ (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 // Debounce via rAF — multiple rapid calls (e.g. afterCommand + button click)\n // collapse into a single update per animation frame.\n if (this._refreshRaf) cancelAnimationFrame(this._refreshRaf);\n this._refreshRaf = requestAnimationFrame(() => {\n this._refreshRaf = null;\n this._doRefresh();\n });\n }\n\n _doRefresh() {\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(/** @type {HTMLElement} */ (btn).dataset.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 /** @type {HTMLButtonElement} */ (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(/** @type {HTMLElement} */ (select).dataset.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?.[0]\n || '';\n }\n // Try to match against available options (case-insensitive)\n const sel = /** @type {HTMLSelectElement} */ (select);\n const matched = Array.from(sel.options).find(\n (opt) => opt.value?.toLowerCase() === raw.toLowerCase()\n );\n sel.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 * Tears down and re-renders the toolbar in-place.\n * Call after registering new buttons post-create via context.use(plugin)\n * or AutumnNote.registerButton() to make them appear in the toolbar.\n */\n rebuild() {\n if (this._refreshRaf) { cancelAnimationFrame(this._refreshRaf); this._refreshRaf = null; }\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this.el) this.el.innerHTML = '';\n this._faReady = this._detectFontAwesome();\n this._buildButtons();\n this._btnMap = new Map(\n (this.options.toolbar || []).flat()\n .map(_resolveBtn).filter(Boolean).map((b) => [b.name, b]),\n );\n this.refresh();\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';\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', role: 'status', 'aria-live': 'polite', 'aria-atomic': 'true' });\n this._charCountEl = createElement('span', { class: 'an-char-count', 'aria-live': 'polite', 'aria-atomic': 'true' });\n const info = createElement('div', { class: 'an-status-info', 'aria-label': 'Editor statistics' });\n info.appendChild(this._wordCountEl);\n info.appendChild(this._charCountEl);\n this.el.appendChild(info);\n\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 this.el?.remove();\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 + /** @type {HTMLElement} */ (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 // Editor.afterCommand() already invokes 'statusbar.update' on every native\n // 'input' event and after every toolbar/formatting command, so a separate\n // content listener here would just re-run this on the same keystroke.\n update() {\n if (!this._wordCountEl || !this._charCountEl) return;\n const editable = this.context.layoutInfo.editable;\n // textContent is faster than innerText (no layout flush, no CSS visibility check)\n const text = editable.textContent || '';\n const words = _countWords(text);\n const chars = text.replaceAll('\\n', '').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 || '').replaceAll('\\n', '').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?.size) return;\n const imgs = /** @type {Element[]} */ ([]);\n if (node.nodeName === 'IMG') {\n imgs.push(/** @type {Element} */ (node));\n } else if (/** @type {Element} */ (node).querySelectorAll) {\n imgs.push(.../** @type {Element} */ (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*(&nbsp;)?\\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 el.remove();\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 * Normalizes task lists from external sources (GitHub, GitLab, etc.) so they\n * pass the sanitiser's `ul.an-checklist` guard. Runs before sanitiseHTML().\n * @param {string} html\n * @returns {string}\n */\n _normalizeExternalTaskLists(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n for (const cb of doc.querySelectorAll('input[type=\"checkbox\"]')) {\n const li = cb.closest('li');\n const ul = li?.closest('ul');\n if (!li || !ul || ul.classList.contains('an-checklist')) continue;\n ul.classList.add('an-checklist');\n cb.removeAttribute('disabled');\n cb.setAttribute('contenteditable', 'false');\n for (const attr of Array.from(cb.attributes)) {\n if (!['type', 'checked', 'contenteditable'].includes(attr.name)) {\n cb.removeAttribute(attr.name);\n }\n }\n }\n return doc.body.innerHTML;\n }\n\n /**\n * Checks whether an HTML payload has no semantic markup beyond plain\n * wrapper elements (e.g. a bare <div>/<p>). Used to decide whether a\n * markdown-shaped plain-text paste should win over an accompanying HTML\n * payload that isn't actually carrying any real rich-text formatting.\n * @param {string} html\n * @returns {boolean}\n */\n _isTriviallyPlainHtml(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n const SIGNIFICANT = 'a,img,table,ul,ol,li,blockquote,pre,code,h1,h2,h3,h4,h5,h6,strong,b,em,i,u,s,del,strike,hr,br';\n return !doc.body.querySelector(SIGNIFICANT);\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 || /** @type {any} */ (globalThis).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 // Enforce maxPasteSize limit (default 5 MB)\n const maxBytes = (this.options.maxPasteSize ?? 5) * 1024 * 1024;\n if (maxBytes > 0) {\n const text = clipboardData.getData('text/plain') || '';\n const html = clipboardData.getData('text/html') || '';\n const size = Math.max(text.length, html.length);\n if (size > maxBytes) {\n event.preventDefault();\n const message = `Pasted content (${size} bytes) exceeds the ${this.options.maxPasteSize ?? 5} MB paste size limit.`;\n this.context.triggerEvent('pasteError', { size, maxBytes, message });\n console.warn(`[AutumnNote] ${message}`);\n return;\n }\n }\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 — when there's no HTML on the clipboard, or the\n // accompanying HTML has no semantic markup (e.g. some terminal/clipboard\n // tools put both a markdown-shaped text/plain and a trivial <div>-wrapped\n // text/html on the clipboard). Real rich-text sources (Word, Docs, etc.)\n // always have semantic tags after cleaning, so this is unaffected.\n if (this.options.markdownPaste !== false) {\n const hasHtml = clipboardData.types.includes('text/html');\n const html = hasHtml ? clipboardData.getData('text/html') : '';\n const htmlTriviallyPlain = !hasHtml || this._isTriviallyPlainHtml(html);\n const text = clipboardData.getData('text/plain');\n if (text && htmlTriviallyPlain && isMarkdown(text)) {\n event.preventDefault();\n const converted = sanitiseHTML(markdownToHTML(text));\n execCommand('insertHTML', converted);\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 = /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 = this._normalizeExternalTaskLists(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 }\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?.files?.length) return;\n\n const imageFiles = Array.from(dt.files).filter((f) => f.type.startsWith('image/'));\n if (imageFiles.length > 0) {\n event.preventDefault();\n event.stopPropagation();\n // Place the caret at the drop coordinates before inserting\n this._placeCaretAtPoint(event.clientX, event.clientY);\n this._insertImageFiles(imageFiles);\n return;\n }\n\n if (this.options.markdownPaste !== false) {\n const mdFile = Array.from(dt.files).find((f) => /\\.md$/i.test(f.name) || f.type === 'text/markdown');\n if (mdFile) {\n event.preventDefault();\n event.stopPropagation();\n this._placeCaretAtPoint(event.clientX, event.clientY);\n this._insertMarkdownFile(mdFile);\n }\n }\n }\n\n /**\n * Reads a dropped `.md` File and inserts it converted to HTML at the\n * current caret. Skips the isMarkdown() heuristic — an explicit `.md`\n * extension/MIME type is an unambiguous signal, unlike pasted plain text.\n * @param {File} file\n */\n _insertMarkdownFile(file) {\n const maxBytes = (this.options.maxPasteSize ?? 5) * 1024 * 1024;\n if (maxBytes > 0 && file.size > maxBytes) {\n const message = `Dropped file \"${file.name}\" (${file.size} bytes) exceeds the ${this.options.maxPasteSize ?? 5} MB paste size limit.`;\n this.context.triggerEvent('pasteError', { size: file.size, maxBytes, message });\n console.warn(`[AutumnNote] ${message}`);\n return;\n }\n const reader = new FileReader();\n reader.onload = (e) => {\n const html = sanitiseHTML(markdownToHTML(/** @type {string} */ (e.target.result) || ''));\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n };\n reader.onerror = () => {\n const message = `Failed to read dropped markdown file \"${file.name}\".`;\n console.warn(`[AutumnNote] ${message}`);\n this.context.triggerEvent('pasteError', { message });\n };\n reader.readAsText(file);\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 = new Set(['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?.type?.startsWith('image/')) return;\n if (UNSUPPORTED.has(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.compressAndRegister(file).then((blobUrl) => {\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 * Compresses an image File via canvas and registers the result behind a\n * lightweight blob: URL (see `resolveImages`), so callers never have to hold\n * the full base64 string in the DOM. Shared by paste/drop and ImageDialog's\n * file picker so every image-insertion path gets the same compression.\n * @param {File} file\n * @returns {Promise<string>} blob: URL usable as an <img src>\n */\n async compressAndRegister(file) {\n const processor = this.options.imageProcessor;\n const dataUrl = typeof processor === 'function'\n ? await processor(file, { context: this.context })\n : await this._compressImage(file);\n const blob = this._dataUrlToBlob(dataUrl);\n const blobUrl = URL.createObjectURL(blob);\n this._blobRegistry.set(blobUrl, dataUrl);\n return blobUrl;\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?.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 = /:(.*?);/.exec(header)?.[1] ?? 'image/png';\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, reject) => {\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.onerror = () => reject(new Error('FileReader failed'));\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.onerror = () => reject(new Error('FileReader failed'));\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 = globalThis.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 .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#039;');\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.replaceAll('\\u200B', '').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 this._textarea?.remove();\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 = /** @type {HTMLTextAreaElement} */ (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.remove();\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 (stripped.startsWith('</')) 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(/** @type {KeyboardEvent} */ (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","import { createElement, on, trapFocus, makeDraggable } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\n/**\n * Shared lifecycle and shell-building logic for all modal dialogs.\n * Subclasses implement _buildDialog() for their specific form fields.\n */\nexport class BaseDialog {\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 /** @type {HTMLElement|null} First focusable input; set by subclass in _buildDialog(). */\n this._firstInput = null;\n this._removeTrap = null;\n }\n\n // ---------------------------------------------------------------------------\n // Abstract — subclasses must override\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLElement} */\n _buildDialog() { throw new Error('_buildDialog() must be implemented by subclass'); }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (shared)\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?.parentNode) {\n this._dialog.remove();\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Shared show helpers\n // ---------------------------------------------------------------------------\n\n /** Saves the current selection range before opening the dialog. */\n _saveRange() {\n withSavedRange((range) => { this._savedRange = range; });\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._firstInput?.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 // Shell builders (used by subclass _buildDialog())\n // ---------------------------------------------------------------------------\n\n /**\n * Builds the overlay + box + header shell common to all dialogs.\n * Also wires up draggable and overlay-click-to-close.\n * @param {string} ariaLabel\n * @param {string} iconHtml Raw SVG string for the dialog icon\n * @param {string} titleText\n * @returns {{ overlay: HTMLElement, box: HTMLElement }}\n */\n _buildDialogShell(ariaLabel, iconHtml, titleText) {\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const header = createElement('div', { class: 'an-dialog-header' });\n const iconEl = createElement('span', { class: 'an-dialog-icon' });\n iconEl.innerHTML = iconHtml;\n const titleEl = createElement('h3', { class: 'an-dialog-title' });\n titleEl.textContent = titleText;\n header.appendChild(iconEl);\n header.appendChild(titleEl);\n\n box.appendChild(header);\n overlay.appendChild(box);\n makeDraggable(header, box);\n\n const d = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n this._disposers.push(d);\n\n return { overlay, box };\n }\n\n /**\n * Builds an action button row with a primary insert button and a cancel button.\n * Disposers are registered automatically.\n * @param {string} insertLabel\n * @param {string} cancelLabel\n * @param {() => void} onInsert\n * @returns {HTMLElement}\n */\n _buildButtonRow(insertLabel, cancelLabel, onInsert) {\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 = insertLabel;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = cancelLabel;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n const d1 = on(insertBtn, 'click', onInsert);\n const d2 = on(cancelBtn, 'click', () => this._close());\n this._disposers.push(d1, d2);\n\n return btnRow;\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 } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" 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\nexport class LinkDialog extends BaseDialog {\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 this._saveRange();\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, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);\n\n // URL field\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.url;\n const urlInput = /** @type {HTMLInputElement} */ (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 this._firstInput = urlInput;\n\n // Text field\n const textLabel = createElement('label', { class: 'an-label' });\n textLabel.textContent = L.displayText;\n const textInput = /** @type {HTMLInputElement} */ (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 = /** @type {HTMLInputElement} */ (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 const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());\n\n box.append(urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);\n\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(textInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(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 = globalThis.getSelection();\n let anchor = null;\n if (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 = /** @type {Element} */ (anchor).getAttribute('href') || '';\n this._textInput.value = anchor.textContent || '';\n this._tabCheckbox.checked = /** @type {Element} */ (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","/**\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 } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" 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\nexport class ImageDialog extends BaseDialog {\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * @param {{ beforeInsert?: () => void }} [hooks]\n */\n show({ beforeInsert } = {}) {\n this._beforeInsert = typeof beforeInsert === 'function' ? beforeInsert : null;\n this._saveRange();\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, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);\n\n // URL field\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.imageUrl;\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 this._firstInput = urlInput;\n\n // Alt text\n const altLabel = createElement('label', { class: 'an-label' });\n altLabel.textContent = L.altText;\n const altInput = /** @type {HTMLInputElement} */ (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(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 = /** @type {HTMLInputElement} */ (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\n if (this.options.allowImageUpload !== false) {\n const fileLabel = createElement('label', { class: 'an-label' });\n fileLabel.textContent = L.uploadLabel;\n const fileInput = /** @type {HTMLInputElement} */ (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 const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());\n box.append(btnRow);\n\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(altInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d4, d5);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _onFileChange() {\n if (this.context._alive === false) return;\n const file = this._fileInput?.files?.[0];\n if (!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 // Resize/compress via Clipboard's shared canvas pipeline so a file chosen\n // through this dialog gets the same treatment as a pasted/dropped image\n // instead of embedding the original (potentially multi-MB) file untouched.\n this.context.invoke('clipboard.compressAndRegister', file).then((blobUrl) => {\n if (this.context._alive === false) return;\n this._urlInput.value = blobUrl;\n }).catch((err) => {\n if (this.context._alive === false) return;\n // Compression failed (e.g. canvas unavailable) — fall back to embedding\n // the original file directly.\n console.warn('[AutumnNote] ImageDialog: image compression failed, using original file.', err);\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\n _onInsert() {\n const src = this._urlInput.value.trim();\n const alt = this._altInput.value.trim();\n const alignRadio = this._alignRow?.querySelector('input[name=\"an-img-align\"]:checked');\n const align = alignRadio ? /** @type {HTMLInputElement} */ (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 // Let callers make a deferred DOM change only after the user commits the\n // dialog. SlashMenu uses this to keep \"/image\" intact when the dialog is\n // cancelled and remove it atomically immediately before image insertion.\n const beforeInsert = this._beforeInsert;\n this._beforeInsert = null;\n beforeInsert?.();\n\n this.context.invoke('editor.insertImage', src, alt, align);\n this._close();\n }\n\n _close() {\n this._beforeInsert = null;\n super._close();\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 } from '../core/dom.js';\nimport { sanitiseUrl } from '../core/sanitise.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" 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\nexport class VideoDialog extends BaseDialog {\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n this._saveRange();\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, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, 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 this._firstInput = 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 const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());\n box.append(urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);\n\n // Live URL hint\n const d0 = on(urlInput, 'input', () => {\n const info = this._parseVideoUrl(urlInput.value.trim());\n let hint = '';\n if (info) { hint = this.context.locale.videoDialog.detected(info.type); }\n else if (urlInput.value) { hint = this.context.locale.videoDialog.unknownFormat; }\n hintEl.textContent = hint;\n });\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d0, 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, Number.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 // ---------------------------------------------------------------------------\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 if (!sanitiseUrl(url, { media: true })) return null;\n\n // YouTube watch: https://www.youtube.com/watch?v=ID\n const ytWatch = /(?:youtube\\.com\\/watch\\?(?:.*&)?v=|youtube\\.com\\/embed\\/)([a-zA-Z0-9_-]{11})/.exec(url);\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 = /youtu\\.be\\/([a-zA-Z0-9_-]{11})/.exec(url);\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 = /youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]{11})/.exec(url);\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 = /vimeo\\.com\\/(\\d+)/.exec(url);\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?.type === 'Direct video') {\n const src = info.embedUrl.replaceAll('\"', '%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 = sanitiseUrl(url, { media: true });\n if (!safeSrc) return null;\n\n const escapedSrc = safeSrc.replaceAll('\"', '%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","/**\n * BaseResizer.js — Shared drag-to-resize overlay for selectable embeds.\n *\n * ImageResizer and VideoResizer were ~28% duplicate: identical overlay\n * construction, selection tracking, scroll/resize repositioning and drag maths,\n * differing only in what counts as a target and how the new size is applied.\n * Subclasses now supply just those differences via the hooks below.\n *\n * Mirrors the existing BaseDialog pattern used by the dialog modules.\n */\n\nimport { on } from '../core/dom.js';\n\n/**\n * Eight handle positions. 'pos' is used as CSS class suffix and to determine\n * 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 BaseResizer {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} Currently selected element */\n this._active = null;\n /** @type {HTMLElement|null} */\n this._overlay = null;\n this._disposers = [];\n this._positionRaf = null;\n /** @type {{l:number,t:number,w:number,h:number}|null} Last written overlay box */\n this._lastOverlayPos = null;\n }\n\n // ---------------------------------------------------------------------------\n // Subclass hooks\n // ---------------------------------------------------------------------------\n\n /** CSS class for the overlay element. @returns {string} */\n get _overlayClass() { return 'an-resizer'; }\n\n /** CSS class applied to the selected element. @returns {string} */\n get _selectedClass() { return 'an-selected'; }\n\n /**\n * Resolves an event target to a resizable element.\n * @param {EventTarget|null} _el\n * @returns {HTMLElement|null}\n */\n _findTarget(_el) { return null; }\n\n /**\n * Natural starting dimensions of the target, used as the drag baseline.\n * @param {HTMLElement} _target\n * @returns {{ w: number, h: number }}\n */\n _getStartSize(_target) { return { w: 0, h: 0 }; }\n\n /** Smallest allowed dimensions. @returns {{ minW: number, minH: number }} */\n _getMinSize() { return { minW: 20, minH: 20 }; }\n\n /**\n * Writes the new size to the target (and any inner embed).\n * @param {HTMLElement} _target\n * @param {number} _w\n * @param {number} _h\n */\n _applySize(_target, _w, _h) {}\n\n /**\n * Additional listeners a subclass needs; the returned disposers are torn down\n * with the rest in destroy().\n * @returns {Array<() => void>}\n */\n _extraListeners() { return []; }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\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 target = this._findTarget(e.target);\n if (target) this._select(target);\n }),\n on(document, 'click', (e) => this._onDocClick(e)),\n on(globalThis, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n on(globalThis, 'resize', onWindowResize, { passive: true }),\n on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n ...this._extraListeners(),\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 this._overlay?.remove();\n this._overlay = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** Re-sync overlay position (call after external size changes). */\n updateOverlay() {\n this._updateOverlayPosition();\n }\n\n /** Programmatically clear the current selection. */\n deselect() {\n this._deselect();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n _buildOverlay() {\n const overlay = document.createElement('div');\n overlay.className = this._overlayClass;\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 target = this._findTarget(e.target);\n if (target) {\n // Prevent the browser from dropping the text selection / showing its own\n // native resize affordance.\n e.preventDefault();\n this._select(target);\n }\n }\n\n _onDocClick(e) {\n if (!this._active) return;\n if (this._active.contains(e.target)) return;\n if (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(target) {\n if (this._active && this._active !== target) {\n this._active.classList.remove(this._selectedClass);\n }\n this._active = target;\n this._lastOverlayPos = null; // invalidate position cache on new selection\n target.classList.add(this._selectedClass);\n this._updateOverlayPosition();\n this._overlay.style.display = 'block';\n }\n\n _deselect() {\n if (this._active) {\n this._active.classList.remove(this._selectedClass);\n this._active = 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._active || !this._overlay) return;\n const offsetParent = this._overlay.offsetParent || this._container;\n const containerRect = offsetParent.getBoundingClientRect();\n const rect = this._active.getBoundingClientRect();\n\n // Skip DOM writes when position hasn't changed (common during non-scroll rAF ticks)\n const p = this._lastOverlayPos;\n if (p?.l === rect.left && p.t === rect.top && p.w === rect.width && p.h === rect.height) return;\n this._lastOverlayPos = { l: rect.left, t: rect.top, w: rect.width, h: rect.height };\n\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 target = this._active;\n if (!target) return;\n\n const startX = e.clientX;\n const startY = e.clientY;\n const { w: startW, h: startH } = this._getStartSize(target);\n const { minW, minH } = this._getMinSize();\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(minW, startW + dx);\n if (pos.includes('w')) newW = Math.max(minW, startW - dx);\n if (pos.includes('s')) newH = Math.max(minH, startH + dy);\n if (pos.includes('n')) newH = Math.max(minH, 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(minH, Math.round(newW / aspectRatio));\n } else {\n newW = Math.min(Math.max(minW, Math.round(newH * aspectRatio)), maxW);\n newH = Math.max(minH, Math.round(newW / aspectRatio));\n }\n }\n\n this._applySize(target, newW, newH);\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","// ImageResizer.js - Interactive resize handles for selected images in the editor\nimport { BaseResizer } from './BaseResizer.js';\n\nexport class ImageResizer extends BaseResizer {\n get _overlayClass() { return 'an-image-resizer'; }\n get _selectedClass() { return 'an-image-selected'; }\n\n /** @param {EventTarget|null} el @returns {HTMLImageElement|null} */\n _findTarget(el) {\n return /** @type {HTMLImageElement|null} */ (\n el instanceof Element ? el.closest('img') : null\n );\n }\n\n /** @param {HTMLImageElement} img */\n _getStartSize(img) {\n return {\n w: img.offsetWidth || img.naturalWidth || 100,\n h: img.offsetHeight || img.naturalHeight || 100,\n };\n }\n\n _getMinSize() {\n const min = this.context.options?.minImageSize ?? 20;\n return { minW: min, minH: min };\n }\n\n /** @param {HTMLImageElement} img @param {number} w @param {number} h */\n _applySize(img, w, h) {\n img.style.width = `${w}px`;\n img.style.height = `${h}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLImageElement|null} */\n getActiveImage() {\n return /** @type {HTMLImageElement|null} */ (this._active);\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';\nimport { BaseResizer } from './BaseResizer.js';\n\nexport class VideoResizer extends BaseResizer {\n get _overlayClass() { return 'an-video-resizer'; }\n get _selectedClass() { return 'an-video-selected'; }\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|null} el\n * @returns {HTMLElement|null}\n */\n _findTarget(el) {\n if (!el || !(el instanceof Element)) return null;\n if (el.classList?.contains('an-video-wrapper')) return /** @type {HTMLElement} */ (el);\n return /** @type {HTMLElement|null} */ (el.closest('.an-video-wrapper'));\n }\n\n /** @param {HTMLElement} wrapper */\n _getStartSize(wrapper) {\n return { w: wrapper.offsetWidth || 560, h: wrapper.offsetHeight || 315 };\n }\n\n _getMinSize() {\n return { minW: 80, minH: 45 };\n }\n\n /** @param {HTMLElement} wrapper @param {number} w @param {number} h */\n _applySize(wrapper, w, h) {\n // Resize wrapper and inner embed via CSS only — attribute writes are redundant\n wrapper.style.width = `${w}px`;\n wrapper.style.height = `${h}px`;\n const embed = /** @type {HTMLElement|null} */ (wrapper.querySelector('iframe, video'));\n if (embed) {\n embed.style.width = `${w}px`;\n embed.style.height = `${h}px`;\n }\n }\n\n _extraListeners() {\n const editable = this.context.layoutInfo.editable;\n return [\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\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLElement|null} */\n getActiveWrapper() {\n return this._active;\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 = /** @type {Element} */ (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 = /** @type {Node|null} */ (/** @type {MouseEvent} */ (e).relatedTarget);\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\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?.parentNode) this._el.remove();\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 > globalThis.innerHeight - margin) {\n top = rect.top - tipH - margin;\n }\n if (left + tipW > globalThis.innerWidth - margin) {\n left = globalThis.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?.getAttribute('href');\n if (url) globalThis.open(url, '_blank', 'noopener,noreferrer');\n this._hide();\n }\n\n _copyLink() {\n const url = 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 ta.remove();\n });\n }\n // Brief visual feedback \n if (this._copyBtn) {\n this._copyBtn.classList.add('an-link-tooltip-btn--copied');\n setTimeout(() => 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 = globalThis.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 = globalThis.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","/**\n * BaseMediaTooltip.js — Shared hover-tooltip behaviour for media embeds.\n *\n * ImageTooltip and VideoTooltip duplicated their button factory, show/hide\n * timers and viewport-aware positioning (~22% of both files). Those pieces live\n * here; each subclass keeps only what genuinely differs — which element counts\n * as the target, which buttons the bar contains, and the actions behind them.\n *\n * Mirrors the existing BaseDialog / BaseResizer pattern.\n */\n\nimport { createElement, on } from '../core/dom.js';\n\n/** Delay before a hovered target shows its tooltip. */\nexport const SHOW_DELAY = 100;\n/** Grace period before a tooltip hides after the pointer leaves. */\nexport const HIDE_DELAY = 180;\n\nexport class BaseMediaTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} The tooltip bar */\n this._el = null;\n /** @type {HTMLElement|null} Currently hovered target */\n this._active = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Subclass hooks\n // ---------------------------------------------------------------------------\n\n /**\n * Whether `_scheduleHide` is allowed to start the hide countdown. Subclasses\n * override to pin the tooltip open (e.g. while a video preview is playing).\n * @returns {boolean}\n */\n _canHide() { return true; }\n\n /** Runs just before the tooltip is hidden, for subclass-specific teardown. */\n _beforeHide() {}\n\n // ---------------------------------------------------------------------------\n // Buttons\n // ---------------------------------------------------------------------------\n\n /**\n * Builds a tooltip button and registers its click disposer.\n * @param {string} icon - inline SVG markup\n * @param {string} title\n * @param {() => void} handler\n * @param {boolean} [isDanger]\n * @returns {HTMLElement}\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(target) {\n if (this._active === target && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._active = target;\n this._show(target);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n if (!this._canHide()) return;\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(_target) {\n this._el.style.display = 'flex';\n // Defer positioning: offsetWidth on a newly-visible element forces layout\n requestAnimationFrame(() => {\n if (this._active) this._positionNear(this._active);\n });\n }\n\n _hide() {\n this._beforeHide();\n this._el.style.display = 'none';\n this._active = 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 /**\n * Places the tooltip under the target, flipping above and clamping\n * horizontally when it would leave the viewport.\n * @param {HTMLElement} target\n */\n _positionNear(target) {\n const rect = target.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 > globalThis.innerHeight - margin) top = rect.top - tipH - margin;\n if (left + tipW > globalThis.innerWidth - margin) left = globalThis.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","// 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';\nimport { BaseMediaTooltip } from './BaseMediaTooltip.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\nexport class ImageTooltip extends BaseMediaTooltip {\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 = /** @type {Element} */ (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 = /** @type {Node|null} */ (/** @type {MouseEvent} */ (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 const et = /** @type {Node} */ (e.target);\n if (this._active && !this._active.contains(et) && !this._el.contains(et)) {\n this._hide();\n }\n }),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n this._el?.remove();\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 // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const img = this._active;\n if (!img) return;\n const target = /** @type {HTMLElement} */ (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._active) this._positionNear(this._active); });\n }\n\n _setCenter() {\n const img = this._active;\n if (!img) return;\n const target = /** @type {HTMLElement} */ (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._active) this._positionNear(this._active); });\n }\n\n _resetSize() {\n const img = this._active;\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._active) this._positionNear(this._active); });\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._active;\n if (!img) return;\n // Parse current rotation angle from inline transform\n const current = img.style.transform || '';\n const match = /rotate\\((-?[\\d.]+)deg\\)/.exec(current);\n const prev = match ? Number.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 if (cleaned) {\n img.style.transform = `${cleaned} rotate(${next}deg)`;\n } else {\n img.style.transform = next === 0 ? '' : `rotate(${next}deg)`;\n }\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._active) this._positionNear(this._active); });\n }\n\n _delete() {\n const img = this._active;\n if (!img) return;\n this._hide();\n this.context.invoke('imageResizer.deselect');\n const figure = img.closest('figure.an-figure');\n if (figure) {\n figure.remove();\n } else {\n img.remove();\n }\n this.context.invoke('editor.afterCommand');\n }\n\n _crop() {\n const img = this._active;\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._active;\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 = globalThis.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 = globalThis.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';\nimport { BaseMediaTooltip } from './BaseMediaTooltip.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\nexport class VideoTooltip extends BaseMediaTooltip {\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 target = /** @type {Element} */ (e.target);\n const wrapper = 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 = /** @type {MouseEvent} */ (e).relatedTarget;\n if (!to || (!editable.contains(/** @type {Node} */ (to)) && !this._el.contains(/** @type {Node} */ (to)))) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n const target = /** @type {Node} */ (e.target);\n if (\n this._active &&\n !this._active.contains(target) &&\n !this._el.contains(target)\n ) {\n this._hide();\n }\n }),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\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 this._el?.remove();\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Base hooks — keep the bar pinned while a preview is playing\n // ---------------------------------------------------------------------------\n\n /** @returns {boolean} */\n _canHide() { return !this._previewMode; }\n\n _beforeHide() {\n if (this._previewMode) this._exitPreview();\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 // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const wrapper = this._active;\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._active) this._positionNear(this._active); });\n }\n\n _setCenter() {\n const wrapper = this._active;\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._active) this._positionNear(this._active); });\n }\n\n _resetSize() {\n const wrapper = this._active;\n if (!wrapper) return;\n const embed = /** @type {HTMLElement|null} */ (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._active) this._positionNear(this._active); });\n }\n\n _delete() {\n const wrapper = this._active;\n if (!wrapper) return;\n this._hide();\n this.context.invoke('videoResizer.deselect');\n wrapper.remove();\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._active;\n if (!wrapper) return;\n this._previewMode = true;\n\n // Hide the shield so the iframe / video receives pointer events directly\n const shield = /** @type {HTMLElement|null} */ (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._active;\n if (wrapper) {\n // Restore the shield\n const shield = /** @type {HTMLElement|null} */ (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?.tagName === 'TD' || next?.tagName === 'TH') ? /** @type {HTMLTableCellElement} */ (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 cellShade: `<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=\"M19 11L8.93 3.36a1 1 0 0 0-1.29.08L3.22 7.8a1 1 0 0 0-.07 1.29L11 20\"/><path d=\"m5 14 5-5\"/><path d=\"M22 22a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2c0-1.5 2.5-5 3.5-5s3.5 3.5 3.5 5z\"/></svg>`,\n borderColor: `<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=\"14\" rx=\"1\"/><line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\" stroke-width=\"1.5\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"17\" stroke-width=\"1.5\"/><path d=\"M3 21h18\" stroke-width=\"3\"/></svg>`,\n alignLeft: `<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=\"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\"/></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\"><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"17\" y1=\"12\" x2=\"7\" y2=\"12\"/><line x1=\"19\" y1=\"18\" x2=\"5\" y2=\"18\"/></svg>`,\n alignRight: `<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=\"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\"/></svg>`,\n alignJustify: `<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=\"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\"/></svg>`,\n headerRow: `<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\"/><rect x=\"3\" y=\"3\" width=\"18\" height=\"8\" rx=\"1\" fill=\"currentColor\" opacity=\"0.2\"/><line x1=\"3\" y1=\"11\" x2=\"21\" y2=\"11\"/><line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\"/><line x1=\"9\" y1=\"11\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"11\" x2=\"15\" y2=\"21\"/></svg>`,\n sortAsc: `<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=\"6\" x2=\"11\" y2=\"6\"/><line x1=\"4\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"13\" y2=\"18\"/><path d=\"M15 9l3-3 3 3\"/><line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n sortDesc: `<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=\"6\" x2=\"13\" y2=\"6\"/><line x1=\"4\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"11\" y2=\"18\"/><path d=\"M15 15l3 3 3-3\"/><line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n exportCSV: `<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 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>`,\n cellPadding: `<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\"/><rect x=\"7\" y=\"7\" width=\"10\" height=\"10\" rx=\"0.5\" stroke-dasharray=\"2 1.5\"/></svg>`,\n};\n\nconst SHADE_PRESETS = [\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\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 shade popover\n this._shadePopover = null;\n this._shadeTitleEl = null;\n this._shadeColorStrip = null;\n // Border color popover\n this._borderColorPopover = null;\n this._borderColorTitleEl = null;\n this._borderColorStrip = null;\n this._borderColorNoBtn = 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 this._shadePopover = this._buildCellShadePopover();\n document.body.appendChild(this._shadePopover);\n\n this._borderColorPopover = this._buildBorderColorPopover();\n document.body.appendChild(this._borderColorPopover);\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 on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const table = /** @type {Element} */ (e.target)?.closest('table');\n if (table && editable.contains(table)) {\n const cell = /** @type {Element} */ (e.target)?.closest('td, th');\n if (cell) {\n this._activeCell = cell;\n this._syncShadeStrip();\n }\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 = /** @type {Node|null} */ (/** @type {MouseEvent} */ (e).relatedTarget);\n if (!to || (\n !editable.contains(to) &&\n !this._el.contains(to) &&\n !this._sizePopover?.contains(to)\n )) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._selectMode && this._activeTable?.contains(et)) return;\n if (this._activeTable &&\n !this._activeTable.contains(et) &&\n !this._el.contains(et) &&\n !this._sizePopover?.contains(et) &&\n !this._shadePopover?.contains(et) &&\n !this._borderColorPopover?.contains(et)) {\n this._hide();\n }\n }),\n // Sync shade strip whenever selection moves to a different cell\n on(document, 'selectionchange', () => this._syncShadeStrip()),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\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 // Right edge of a merged cell = last spanned column, not the start column\n _colIdx = getVisualColIndex(_nearCell) + (_nearCell.colSpan || 1) - 1;\n // Cache non-merged cells at that column — merged cells cannot be individually\n // resized per column (F-1: colSpan > 1 distributes width across all spanned cols)\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 // Use the actual column width from a non-merged cell; fall back to per-column estimate\n _startW = _colCells.length > 0\n ? _colCells[0].offsetWidth\n : Math.max(30, Math.round(_nearCell.offsetWidth / (_nearCell.colSpan || 1)));\n document.body.style.cursor = 'col-resize';\n } else {\n // Bottom edge of a merged cell = last spanned row, not the cell's own <tr>\n const tr = _nearCell.closest('tr');\n const rowStart = tr ? Array.from(_table.rows).indexOf(tr) : 0;\n const lastRowIdx = rowStart + (_nearCell.rowSpan || 1) - 1;\n _row = _table.rows[lastRowIdx] || 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?.parentNode) this._el.remove();\n this._el = null;\n if (this._sizePopover?.parentNode) {\n this._sizePopover.remove();\n }\n this._sizePopover = null;\n if (this._shadePopover?.parentNode) {\n this._shadePopover.remove();\n }\n this._shadePopover = null;\n if (this._borderColorPopover?.parentNode) {\n this._borderColorPopover.remove();\n }\n this._borderColorPopover = 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 el.appendChild(this._makeBtn(ICONS.sortAsc, L.sortAsc, () => this._sortColumn('asc')));\n el.appendChild(this._makeBtn(ICONS.sortDesc, L.sortDesc, () => this._sortColumn('desc')));\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 // Cell text alignment\n el.appendChild(this._makeBtn(ICONS.alignLeft, L.cellAlignLeft, () => this._applyCellAlign('left')));\n el.appendChild(this._makeBtn(ICONS.alignCenter, L.cellAlignCenter, () => this._applyCellAlign('center')));\n el.appendChild(this._makeBtn(ICONS.alignRight, L.cellAlignRight, () => this._applyCellAlign('right')));\n el.appendChild(this._makeBtn(ICONS.alignJustify, L.cellAlignJustify, () => this._applyCellAlign('justify')));\n el.appendChild(this._makeBtn(ICONS.headerRow, L.toggleHeaderRow, () => this._toggleHeaderRow()));\n\n el.appendChild(this._sep());\n\n // Cell background shading — uses color-strip variant like foreColor/hiliteColor buttons\n const shadeBtn = createElement('button', {\n type: 'button',\n class: 'an-link-tooltip-btn an-link-tooltip-btn--shade',\n title: L.cellBackground,\n });\n const shadeSvgWrap = createElement('span', { class: 'an-bubble-btn-svg' });\n shadeSvgWrap.innerHTML = ICONS.cellShade;\n const shadeStrip = createElement('span', { class: 'an-link-tooltip-color-strip' });\n shadeBtn.appendChild(shadeSvgWrap);\n shadeBtn.appendChild(shadeStrip);\n this._shadeColorStrip = shadeStrip;\n this._disposers.push(on(shadeBtn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._openCellShadePopover();\n }));\n el.appendChild(shadeBtn);\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 el.appendChild(this._makeBtn(ICONS.cellPadding, L.cellPadding, () => this._openSizePopover('cellPadding')));\n\n // Table border color button — color-strip variant like shade button\n const borderColorBtn = createElement('button', {\n type: 'button',\n class: 'an-link-tooltip-btn an-link-tooltip-btn--shade',\n title: L.tableBorderColor,\n });\n const borderColorSvgWrap = createElement('span', { class: 'an-bubble-btn-svg' });\n borderColorSvgWrap.innerHTML = ICONS.borderColor;\n const borderColorStrip = createElement('span', { class: 'an-link-tooltip-color-strip' });\n borderColorBtn.appendChild(borderColorSvgWrap);\n borderColorBtn.appendChild(borderColorStrip);\n this._borderColorStrip = borderColorStrip;\n this._disposers.push(on(borderColorBtn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._openBorderColorPopover();\n }));\n el.appendChild(borderColorBtn);\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 el.appendChild(this._sep());\n el.appendChild(this._makeBtn(ICONS.exportCSV, L.exportCSV, () => this._exportTableCSV()));\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 if (this._shadePopover && this._shadePopover.style.display !== 'none') return;\n if (this._borderColorPopover && this._borderColorPopover.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 this._syncShadeStrip();\n this._syncBorderColorStrip();\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 _syncShadeStrip() {\n if (!this._shadeColorStrip || !this._el || this._el.style.display === 'none') return;\n const cell = this._getCell();\n this._shadeColorStrip.style.background = cell?.style.backgroundColor || 'transparent';\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 this._hideBorderColorPopover();\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 > globalThis.innerWidth - margin) left = globalThis.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 = globalThis.getSelection();\n if (sel?.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const cellFromSel = /** @type {Element} */ (container)?.closest('td, th');\n if (cellFromSel && this._activeTable?.contains(cellFromSel)) {\n return cellFromSel;\n }\n }\n return this._activeCell\n || 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?.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 if (position === 'above') return ri < bi ? r : best;\n return ri > bi ? r : best;\n }, selectedRows[0]);\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?.style.width) td.style.width = ref.style.width;\n if (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.after(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.remove());\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.remove());\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 = globalThis.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.style.height = '';\n first.style.minHeight = '';\n\n // Merge content: collect non-empty inner HTML, join with <br> separator\n const parts = rectCells\n .map((c) => c.innerHTML.replace(/^(<br\\s*\\/?>|\\s)+$/i, '').trim())\n .filter((h) => h !== '');\n first.innerHTML = parts.length ? parts.join('<br>') : '<br>';\n\n rectCells.slice(1).forEach((c) => {\n const row = c.parentElement;\n c.remove();\n // Remove the parent <tr> if it is now completely empty\n if (row && row.cells.length === 0) row.remove();\n });\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.remove();\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 (&nbsp;); 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?.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 = /** @type {HTMLInputElement} */ (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 = Number.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 const ke = /** @type {KeyboardEvent} */ (e);\n if (ke.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (ke.key === 'Escape') this._hideSizePopover();\n });\n const d4 = on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._sizePopover &&\n this._sizePopover.style.display !== 'none' &&\n !this._sizePopover.contains(et) &&\n !this._el.contains(et)) {\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 ? (Number.parseInt(firstCell.style.borderWidth, 10) ||\n Number.parseInt(globalThis.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 = String(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 if (type === 'cellPadding') {\n const cells = this._getSelectedCells();\n const firstCell = cells[0] || this._getCell();\n const currentPad = firstCell\n ? (Number.parseInt(firstCell.style.padding, 10) ||\n Number.parseInt(firstCell.style.paddingTop, 10) || 4)\n : 4;\n this._sizeTitleEl.textContent = this.context.locale.tooltips.table.cellPaddingPx;\n this._sizeInputEl.min = '0';\n this._sizeInputEl.max = '40';\n this._sizeInputEl.value = String(currentPad);\n this._sizeApply = (val) => {\n const activeCells = this._getSelectedCells();\n activeCells.forEach((c) => { if (c) c.style.padding = `${val}px`; });\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 if (isCol) {\n this._sizeInputEl.value = cell.offsetWidth || 120;\n } else {\n const refRow = cell.closest('tr');\n this._sizeInputEl.value = refRow ? (refRow.offsetHeight || 40) : 40;\n }\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 > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;\n if (top + ph > globalThis.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 // ---------------------------------------------------------------------------\n // Cell background shade popover\n // ---------------------------------------------------------------------------\n\n _buildCellShadePopover() {\n const pop = createElement('div', { class: 'an-cell-shade-popover' });\n pop.style.display = 'none';\n\n const title = createElement('div', { class: 'an-size-popover-title' });\n pop.appendChild(title);\n this._shadeTitleEl = title;\n\n // 24-color palette — reuse existing CSS classes\n const palette = createElement('div', { class: 'an-context-color-palette' });\n SHADE_PRESETS.forEach((color) => {\n const sw = createElement('div', { class: 'an-context-color-swatch', title: color });\n sw.style.background = color;\n this._disposers.push(on(sw, 'click', (e) => {\n e.stopPropagation();\n this._applyCellShade(color);\n }));\n palette.appendChild(sw);\n });\n pop.appendChild(palette);\n\n // \"No shading\" row — clears background color\n const noShadeRow = createElement('div', { class: 'an-context-color-custom' });\n const noShadeBtn = createElement('button', { type: 'button', class: 'an-shade-no-color' });\n this._disposers.push(on(noShadeBtn, 'click', () => this._applyCellShade('')));\n noShadeRow.appendChild(noShadeBtn);\n pop.appendChild(noShadeRow);\n this._shadeNoBtn = noShadeBtn;\n\n // Custom color input\n const customRow = createElement('div', { class: 'an-context-color-custom' });\n const colorInput = /** @type {HTMLInputElement} */ (createElement('input', { type: 'color', class: 'an-shade-color-input', value: '#ffffff' }));\n const customLabel = createElement('span');\n customLabel.textContent = this.context.locale.contextMenu.customColorLabel;\n this._disposers.push(on(colorInput, 'change', () => this._applyCellShade(colorInput.value)));\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n pop.appendChild(customRow);\n\n // Prevent mousedown from collapsing editor selection; keep tooltip alive while hovering\n this._disposers.push(\n on(pop, 'mousedown', (e) => e.preventDefault()),\n on(pop, 'mouseenter', () => this._clearTimers()),\n on(pop, 'mouseleave', () => this._scheduleHide()),\n // Close on outside click\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._shadePopover &&\n this._shadePopover.style.display !== 'none' &&\n !this._shadePopover.contains(et) &&\n !this._el?.contains(et)) {\n this._hideCellShadePopover();\n }\n }),\n );\n\n return pop;\n }\n\n _openCellShadePopover() {\n if (!this._shadePopover) return;\n const L = this.context.locale.tooltips.table;\n if (this._shadeTitleEl) this._shadeTitleEl.textContent = L.cellBackground;\n if (this._shadeNoBtn) this._shadeNoBtn.textContent = L.noShading;\n\n this._shadePopover.style.display = 'block';\n requestAnimationFrame(() => {\n if (!this._shadePopover || !this._el) return;\n const pw = this._shadePopover.offsetWidth || 170;\n const ph = this._shadePopover.offsetHeight || 120;\n const tipRect = this._el.getBoundingClientRect();\n let left = tipRect.left;\n let top = tipRect.bottom + 6;\n if (left + pw > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;\n if (top + ph > globalThis.innerHeight - 8) top = tipRect.top - ph - 6;\n this._shadePopover.style.left = `${Math.max(8, left)}px`;\n this._shadePopover.style.top = `${Math.max(8, top)}px`;\n });\n }\n\n _hideCellShadePopover() {\n if (this._shadePopover) this._shadePopover.style.display = 'none';\n }\n\n _applyCellShade(color) {\n const cells = this._selectMode ? this._selectedCells : [this._getCell()];\n cells.forEach((cell) => {\n if (cell) cell.style.backgroundColor = color;\n });\n // Update the color strip on the shade button to reflect the applied color\n if (this._shadeColorStrip) {\n this._shadeColorStrip.style.background = color || 'transparent';\n }\n this._hideCellShadePopover();\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Table border color popover\n // ---------------------------------------------------------------------------\n\n _buildBorderColorPopover() {\n const pop = createElement('div', { class: 'an-cell-shade-popover' });\n pop.style.display = 'none';\n\n const title = createElement('div', { class: 'an-size-popover-title' });\n pop.appendChild(title);\n this._borderColorTitleEl = title;\n\n const palette = createElement('div', { class: 'an-context-color-palette' });\n SHADE_PRESETS.forEach((color) => {\n const sw = createElement('div', { class: 'an-context-color-swatch', title: color });\n sw.style.background = color;\n this._disposers.push(on(sw, 'click', (e) => {\n e.stopPropagation();\n this._applyBorderColor(color);\n }));\n palette.appendChild(sw);\n });\n pop.appendChild(palette);\n\n const noColorRow = createElement('div', { class: 'an-context-color-custom' });\n const noColorBtn = createElement('button', { type: 'button', class: 'an-shade-no-color' });\n this._disposers.push(on(noColorBtn, 'click', () => this._applyBorderColor('')));\n noColorRow.appendChild(noColorBtn);\n pop.appendChild(noColorRow);\n this._borderColorNoBtn = noColorBtn;\n\n const customRow = createElement('div', { class: 'an-context-color-custom' });\n const colorInput = /** @type {HTMLInputElement} */ (createElement('input', { type: 'color', class: 'an-shade-color-input', value: '#000000' }));\n const customLabel = createElement('span');\n customLabel.textContent = this.context.locale.contextMenu.customColorLabel;\n this._disposers.push(on(colorInput, 'change', () => this._applyBorderColor(colorInput.value)));\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n pop.appendChild(customRow);\n\n this._disposers.push(\n on(pop, 'mousedown', (e) => e.preventDefault()),\n on(pop, 'mouseenter', () => this._clearTimers()),\n on(pop, 'mouseleave', () => this._scheduleHide()),\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._borderColorPopover &&\n this._borderColorPopover.style.display !== 'none' &&\n !this._borderColorPopover.contains(et) &&\n !this._el?.contains(et)) {\n this._hideBorderColorPopover();\n }\n }),\n );\n\n return pop;\n }\n\n _openBorderColorPopover() {\n if (!this._borderColorPopover) return;\n const L = this.context.locale.tooltips.table;\n if (this._borderColorTitleEl) this._borderColorTitleEl.textContent = L.tableBorderColor;\n if (this._borderColorNoBtn) this._borderColorNoBtn.textContent = L.noBorderColor;\n\n this._borderColorPopover.style.display = 'block';\n requestAnimationFrame(() => {\n if (!this._borderColorPopover || !this._el) return;\n const pw = this._borderColorPopover.offsetWidth || 170;\n const ph = this._borderColorPopover.offsetHeight || 120;\n const tipRect = this._el.getBoundingClientRect();\n let left = tipRect.left;\n let top = tipRect.bottom + 6;\n if (left + pw > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;\n if (top + ph > globalThis.innerHeight - 8) top = tipRect.top - ph - 6;\n this._borderColorPopover.style.left = `${Math.max(8, left)}px`;\n this._borderColorPopover.style.top = `${Math.max(8, top)}px`;\n });\n }\n\n _hideBorderColorPopover() {\n if (this._borderColorPopover) this._borderColorPopover.style.display = 'none';\n }\n\n _applyBorderColor(color) {\n const table = this._activeTable;\n if (!table) return;\n Array.from(table.querySelectorAll('td, th')).forEach((c) => { c.style.borderColor = color; });\n if (this._borderColorStrip) {\n this._borderColorStrip.style.background = color || 'transparent';\n }\n this._hideBorderColorPopover();\n this.context.invoke('editor.afterCommand');\n }\n\n _syncBorderColorStrip() {\n if (!this._borderColorStrip || !this._el || this._el.style.display === 'none') return;\n const firstCell = this._activeTable?.querySelector('td, th');\n this._borderColorStrip.style.background = firstCell?.style.borderColor || 'transparent';\n }\n\n // ---------------------------------------------------------------------------\n // Cell text alignment\n // ---------------------------------------------------------------------------\n\n _applyCellAlign(align) {\n const cells = this._getSelectedCells();\n cells.forEach((c) => { if (c) c.style.textAlign = align; });\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Toggle header row\n // ---------------------------------------------------------------------------\n\n _toggleHeaderRow() {\n const table = this._activeTable;\n if (!table) return;\n const firstRow = table.querySelector('tr');\n if (!firstRow) return;\n\n const isInThead = firstRow.closest('thead') !== null;\n\n if (isInThead) {\n // Convert th → td and move row to tbody\n let tbody = table.querySelector('tbody');\n if (!tbody) {\n tbody = document.createElement('tbody');\n table.appendChild(tbody);\n }\n Array.from(firstRow.cells).forEach((cell) => {\n const td = document.createElement('td');\n td.innerHTML = cell.innerHTML;\n td.style.cssText = cell.style.cssText;\n firstRow.replaceChild(td, cell);\n });\n tbody.insertBefore(firstRow, tbody.firstChild);\n const thead = table.querySelector('thead');\n if (thead && thead.rows.length === 0) thead.remove();\n } else {\n // Convert td → th and move row to thead\n let thead = table.querySelector('thead');\n if (!thead) {\n thead = document.createElement('thead');\n table.insertBefore(thead, table.firstChild);\n }\n Array.from(firstRow.cells).forEach((cell) => {\n const th = document.createElement('th');\n th.innerHTML = cell.innerHTML;\n th.style.cssText = cell.style.cssText;\n firstRow.replaceChild(th, cell);\n });\n thead.appendChild(firstRow);\n }\n\n this.context.invoke('editor.afterCommand');\n }\n\n _sortColumn(direction) {\n const table = this._activeTable;\n if (!table) return;\n const cell = this._getCell();\n if (!cell) return;\n const colIdx = getVisualColIndex(cell);\n if (colIdx === -1) return;\n const tbody = table.querySelector('tbody') || table;\n const rows = Array.from(tbody.querySelectorAll(':scope > tr'));\n if (rows.length < 2) return;\n rows.sort((a, b) => {\n const aCell = getCellAtVisualCol(a, colIdx);\n const bCell = getCellAtVisualCol(b, colIdx);\n const aText = (aCell?.textContent || '').trim();\n const bText = (bCell?.textContent || '').trim();\n const aNum = parseFloat(aText);\n const bNum = parseFloat(bText);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return direction === 'asc' ? aNum - bNum : bNum - aNum;\n }\n return direction === 'asc'\n ? aText.localeCompare(bText)\n : bText.localeCompare(aText);\n });\n rows.forEach((row) => tbody.appendChild(row));\n this._markSortIndicator(table, colIdx, direction);\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Marks the header cell of the sorted column with `an-sort-asc`/`an-sort-desc`\n * so the active sort column and direction are visible, and clears any previous\n * indicator. No-op for tables without a `<thead>` (no header row to mark).\n * @param {HTMLTableElement} table\n * @param {number} colIdx\n * @param {'asc'|'desc'} direction\n */\n _markSortIndicator(table, colIdx, direction) {\n const thead = table.querySelector('thead');\n if (!thead) return;\n thead.querySelectorAll('.an-sort-asc, .an-sort-desc').forEach((el) => {\n el.classList.remove('an-sort-asc', 'an-sort-desc');\n });\n const headerRow = thead.querySelector('tr');\n if (!headerRow) return;\n const headerCell = getCellAtVisualCol(headerRow, colIdx);\n if (headerCell) headerCell.classList.add(direction === 'asc' ? 'an-sort-asc' : 'an-sort-desc');\n }\n\n _exportTableCSV() {\n const table = this._activeTable;\n if (!table) return;\n const rows = Array.from(table.querySelectorAll('tr'));\n const csv = rows.map((row) =>\n Array.from(row.querySelectorAll('td, th'))\n .map((cell) => {\n const text = (cell.textContent || '').trim().replace(/\"/g, '\"\"');\n return `\"${text}\"`;\n })\n .join(',')\n ).join('\\n');\n const blob = new Blob(['' + csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'table.csv';\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(url);\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 lineNumbers: `<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=\"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 6h1v4\"/><path d=\"M4 10h2\"/><path d=\"M6 18H4c0-1 2-2 2-3s-1-2-2-2\"/></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._wrapBtn = null;\n this._lineNumbersBtn = 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 = /** @type {Element} */ (e.target)?.closest('pre');\n if (pre && editable.contains(pre)) {\n this._scheduleShow(pre);\n }\n }),\n on(editable, 'mouseout', (e) => {\n const to = /** @type {Node|null} */ (/** @type {MouseEvent} */ (e).relatedTarget);\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._activePre &&\n !this._activePre.contains(et) &&\n !this._el.contains(et)) {\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 this._el?.remove();\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 = /** @type {HTMLSelectElement} */ (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'], ['scss', 'SCSS'],\n ['json', 'JSON'], ['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 // Toggle line numbers\n this._lineNumbersBtn = this._makeBtn(ICONS.lineNumbers, L.lineNumbers, () => this._toggleLineNumbers());\n el.appendChild(this._lineNumbersBtn);\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._syncLineNumbersBtn();\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 > globalThis.innerWidth - margin) left = globalThis.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 || globalThis.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 _syncLineNumbersBtn() {\n if (!this._activePre || !this._lineNumbersBtn) return;\n const on = this._activePre.classList.contains('an-code-line-numbers');\n this._lineNumbersBtn.classList.toggle('active', on);\n this._lineNumbersBtn.title = this.context.locale.tooltips.code.lineNumbers;\n }\n\n _syncLangSelect() {\n if (!this._activePre || !this._langSelect) return;\n const codeEl = this._activePre.querySelector('code');\n const fromAttr = this._activePre.dataset.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 (_) { void _; }\n ta.remove();\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 _toggleLineNumbers() {\n const pre = this._activePre;\n if (!pre) return;\n pre.classList.toggle('an-code-line-numbers');\n this._syncLineNumbersBtn();\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Applies a language to a given <pre> element: sets classes, data-language,\n * and triggers Prism highlighting. Called by the auto-detect flow.\n * @param {HTMLElement} pre\n * @param {string} lang - Prism language identifier, e.g. 'javascript'\n */\n applyLanguage(pre, lang) {\n if (!pre || !lang) return;\n // Temporarily set activePre so _onLangChange can target it\n const savedPre = this._activePre;\n this._activePre = pre;\n if (this._langSelect) this._langSelect.value = lang;\n this._onLangChange();\n // Update the select to reflect the detected language when tooltip is shown\n if (this._langSelect) this._langSelect.value = lang;\n this._activePre = savedPre || pre;\n // Don't restore savedPre if it was null — keep `pre` as activePre so that\n // the tooltip select is correct the first time the user hovers over it.\n }\n\n _onLangChange() {\n const pre = this._activePre;\n if (!pre) return;\n const lang = this._langSelect.value;\n const _w = /** @type {any} */ (globalThis);\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.dataset.language = lang;\n } else {\n delete pre.dataset.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 _w.Prism.highlightElement(codeEl);\n this.context.invoke('editor.afterCommand');\n };\n\n if (lang) {\n if (_w.Prism !== undefined) {\n // Grammar already loaded — highlight immediately\n if (_w.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 (_w.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 const _w = /** @type {any} */ (globalThis);\n if (!this.context.options.codeHighlight || _w.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 = _w.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 _w = /** @type {any} */ (globalThis);\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 (_w.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', /** @type {EventListener} */ (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 pre.remove();\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, makeDraggable } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\n/**\n * Resolved emoji catalogue, shared by every editor instance on the page.\n * @type {{ EMOJI_CATS: Array, EMOJI_LIST: Array }|null}\n */\nlet _emojiData = null;\n/** @type {Promise<{ EMOJI_CATS: Array, EMOJI_LIST: Array }>|null} */\nlet _emojiDataPromise = null;\n\n/**\n * Loads the emoji catalogue on first use. The table is ~25 KB (≈6 KB gzip),\n * so it is split into its own chunk rather than shipped to every consumer —\n * including those whose toolbar never shows an emoji button.\n * @returns {Promise<{ EMOJI_CATS: Array, EMOJI_LIST: Array }>}\n */\nfunction loadEmojiData() {\n if (_emojiData) return Promise.resolve(_emojiData);\n _emojiDataPromise ??= import('./emoji-data.js').then((mod) => {\n _emojiData = { EMOJI_CATS: mod.EMOJI_CATS, EMOJI_LIST: mod.EMOJI_LIST };\n return _emojiData;\n });\n return _emojiDataPromise;\n}\n\n// ---------------------------------------------------------------------------\n// Dialog class\n// ---------------------------------------------------------------------------\n\nexport class EmojiDialog extends BaseDialog {\n _activeCat = 'all';\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n // Grid is built lazily in show() to avoid ~500 DOM nodes at load time.\n return this;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the picker, fetching the emoji catalogue chunk on first call.\n * Awaiting is optional — the dialog opens on its own once data arrives.\n * @returns {Promise<void>}\n */\n async show() {\n // Capture the caret before awaiting: the selection must be read while the\n // click that opened the dialog is still the current interaction.\n this._saveRange();\n\n if (!this._dialog) {\n const { EMOJI_CATS, EMOJI_LIST } = await loadEmojiData();\n // A second show() may have won the race while this one awaited.\n if (!this._dialog) {\n this._cats = EMOJI_CATS;\n this._list = EMOJI_LIST;\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\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 titleGroup = createElement('div', { class: 'an-dialog-title-group' });\n const iconEl = createElement('span', { class: 'an-dialog-icon an-dialog-icon--sm' });\n iconEl.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 13s1.5 2 4 2 4-2 4-2\"/><line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\"/><line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\"/></svg>`;\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n titleGroup.append(iconEl, title);\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '&times;';\n titleRow.append(titleGroup, closeBtn);\n\n // Search\n const searchInput = /** @type {HTMLInputElement} */ (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 this._cats.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = 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 this._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 this._firstInput = searchInput;\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 makeDraggable(titleRow, 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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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', /** @type {HTMLElement} */ (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 hCell = /** @type {HTMLElement} */ (cell);\n const matchCat = !cat || cat === 'all' || hCell.dataset.cat === cat;\n const matchQuery = !q || hCell.dataset.keywords.includes(q) || hCell.dataset.char === q;\n const visible = matchCat && matchQuery;\n hCell.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 /** @type {HTMLElement} */ (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 = globalThis.getSelection();\n let range = 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 = /** @type {Element|null} */ (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest('td, th');\n range.deleteContents();\n if (_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","/**\n * IconDialog.js - Browse and insert FontAwesome Free icons\n */\n\nimport { createElement, on, makeDraggable } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.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 extends BaseDialog {\n _selectedIcon = null;\n _activeCat = 'all';\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this._ensureFontAwesome();\n // Grid is built lazily in show() to avoid ~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) => /** @type {HTMLLinkElement} */ (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 // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n if (!this._dialog) {\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\n this._saveRange();\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 titleGroup = createElement('div', { class: 'an-dialog-title-group' });\n const iconEl = createElement('span', { class: 'an-dialog-icon an-dialog-icon--sm' });\n iconEl.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/></svg>`;\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n titleGroup.append(iconEl, title);\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '&times;';\n titleRow.append(titleGroup, closeBtn);\n\n // Search\n const searchInput = /** @type {HTMLInputElement} */ (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 this._firstInput = 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?.[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 = /** @type {HTMLSelectElement} */ (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 = /** @type {HTMLSelectElement} */ (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 = /** @type {HTMLOptionElement} */ (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 = /** @type {HTMLInputElement} */ (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 = /** @type {HTMLInputElement} */ (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 makeDraggable(titleRow, 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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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', /** @type {HTMLElement} */ (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 hCell = /** @type {HTMLElement} */ (cell);\n const name = hCell.dataset.name;\n const cellCat = hCell.dataset.cat;\n const matchesCat = !cat || cat === 'all' || cellCat === cat;\n const matchesQuery = !q || name.includes(q);\n const visible = matchesCat && matchesQuery;\n hCell.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 /** @type {HTMLElement} */ (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', /** @type {HTMLElement} */ (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?.value || 'fa-solid';\n const size = this._sizeSelect?.value || '1em';\n const useColor = this._useColorCb?.checked ?? false;\n const color = useColor ? (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?.value || 'fa-solid';\n const size = this._sizeSelect?.value || '';\n const useColor = this._useColorCb?.checked ?? false;\n const color = useColor ? (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 = globalThis.getSelection();\n let range = (sel?.rangeCount ?? 0) > 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 = /** @type {Element|null} */ (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest('td, th');\n range.deleteContents();\n if (_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?.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 _close() {\n this._selectedIcon = null;\n super._close();\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?.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)).catch(() => {});\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?.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?.editable;\n if (editable) {\n this._disposers.push(on(editable, 'contextmenu', (e) => this._onContextMenu(e)));\n }\n\n this._disposers.push(\n on(document, 'click', (e) => this._maybeHide(e)),\n on(document, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Escape') this.hide(); }),\n on(globalThis, 'scroll', () => this.hide(), { passive: true }),\n );\n\n return this;\n }\n\n destroy() {\n this._menuDisposers.forEach((d) => { try { d(); } catch (_e) { void _e; } });\n this._menuDisposers = [];\n this._disposers.forEach((d) => { try { d(); } catch (_e) { void _e; } });\n this._disposers = [];\n if (this.el) this.el.remove();\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 = Number.parseFloat(this.el.style.left);\n const curTop = Number.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 = Number.parseFloat(this.el.style.left);\n const curTop = Number.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 = /** @type {HTMLInputElement} */ (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) ? `${rows} × ${cols}` : (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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?.editable;\n if (editable && this._savedRange) {\n editable.focus();\n const sel = globalThis.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) /** @type {HTMLButtonElement} */ (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?.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 = globalThis.getSelection();\n this._savedRange = (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 const 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 (_) { void _; }\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 ? this._lastX : x;\n const ry = y === undefined ? this._lastY : y;\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 > globalThis.innerWidth - 8) left = globalThis.innerWidth - w - 8;\n if (left < 8) left = 8;\n if (top + h > globalThis.innerHeight - 8) top = globalThis.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 = globalThis.getComputedStyle(/** @type {Element} */ (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?.editable;\n if (!editable || !this._savedRange) return;\n editable.focus();\n const sel = globalThis.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?.editable;\n let node = range.startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || !editable?.contains(node)) return;\n\n // Walk up to collect explicitly-set inline properties from the nearest styled ancestor\n const cs = globalThis.getComputedStyle(/** @type {Element} */ (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: Number.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?.[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?.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 = globalThis.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)) /** @type {HTMLElement} */ (el).dataset.anTmp = 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.remove();\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?.editable;\n if (!editable) return;\n\n editable.focus();\n const sel = globalThis.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)) /** @type {Element} */ (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 } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.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\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"7\" width=\"20\" height=\"14\" rx=\"2\"/><path d=\"M6 11h.01M10 11h.01M14 11h.01M18 11h.01M6 15h.01M18 15h.01M10 15h4\"/><path d=\"M7 3l5 4 5-4\"/></svg>`;\n\nexport class ShortcutsDialog extends BaseDialog {\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.shortcutsDialog;\n const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);\n box.classList.add('an-shortcuts-box');\n\n // Close button pinned to the right of the header row\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n 'aria-label': L.close,\n style: 'margin-left:auto',\n });\n closeBtn.textContent = '×';\n this._closeBtn = closeBtn;\n this._firstInput = closeBtn;\n box.querySelector('.an-dialog-header').appendChild(closeBtn);\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 const d1 = on(closeBtn, 'click', () => this._close());\n this._disposers.push(d1);\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, makeDraggable } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nexport class FindReplace extends BaseDialog {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n super(context);\n\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 this._useRegex = false;\n this._wholeWord = 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 this._lastUseRegex = null;\n this._lastWholeWord = null;\n\n this._focusTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n destroy() {\n clearTimeout(this._focusTimer);\n this._focusTimer = null;\n this._clearHighlights();\n super.destroy();\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) /** @type {HTMLElement} */ (replaceRow).style.display = isReplace ? '' : 'none';\n if (replaceActions) /** @type {HTMLElement} */ (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 an-fr-box' });\n\n // ---- Header: [icon][title] [×] ----\n const header = createElement('div', { class: 'an-fr-header' });\n const titleGroup = createElement('div', { class: 'an-dialog-title-group' });\n const iconEl = createElement('span', { class: 'an-dialog-icon an-dialog-icon--sm' });\n iconEl.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/></svg>`;\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.findTitle;\n titleGroup.append(iconEl, title);\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n title: L.close,\n 'aria-label': L.close,\n });\n closeBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n this._closeBtn = closeBtn;\n header.append(titleGroup, closeBtn);\n box.appendChild(header);\n\n // ---- Search bar: [input] [Aa] [↑] [↓] counter ----\n const searchBar = createElement('div', { class: 'an-fr-search-bar' });\n const findInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'text',\n class: 'an-input an-fr-input',\n placeholder: L.findPlaceholder,\n 'aria-label': L.searchAriaLabel,\n }));\n this._findInput = findInput;\n\n // Case-sensitive toggle (visual button; hidden checkbox kept for state)\n const caseCheckbox = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'checkbox',\n style: 'display:none',\n 'aria-hidden': 'true',\n }));\n this._caseCheckbox = caseCheckbox;\n const caseBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: 'Case sensitive',\n 'aria-label': 'Case sensitive',\n });\n caseBtn.textContent = 'Aa';\n\n const regexBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: L.useRegex,\n 'aria-label': L.useRegex,\n });\n regexBtn.textContent = '.*';\n\n const wholeWordBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: L.wholeWord,\n 'aria-label': L.wholeWord,\n });\n wholeWordBtn.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\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"7\" width=\"18\" height=\"10\" rx=\"2\"/><line x1=\"7\" y1=\"21\" x2=\"7\" y2=\"17\"/><line x1=\"17\" y1=\"21\" x2=\"17\" y2=\"17\"/></svg>`;\n\n const prevBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: 'Previous (Shift+Enter)',\n 'aria-label': 'Previous',\n });\n prevBtn.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=\"18 15 12 9 6 15\"/></svg>`;\n\n const nextBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: 'Next (Enter)',\n 'aria-label': 'Next',\n });\n nextBtn.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=\"6 9 12 15 18 9\"/></svg>`;\n\n const counter = createElement('span', { class: 'an-fr-counter' });\n this._counterEl = counter;\n\n searchBar.append(findInput, caseCheckbox, caseBtn, regexBtn, wholeWordBtn, prevBtn, nextBtn, counter);\n box.appendChild(searchBar);\n\n // ---- Replace row: [input] [Replace] [All] (hidden by default) ----\n const replaceRow = createElement('div', { class: 'an-fr-replace-row' });\n replaceRow.style.display = 'none';\n const replaceInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'text',\n class: 'an-input an-fr-input',\n placeholder: L.replacePlaceholder,\n 'aria-label': L.replaceAriaLabel,\n }));\n this._replaceInput = replaceInput;\n const replaceBtn = createElement('button', { type: 'button', class: 'an-btn an-fr-replace-btn' });\n replaceBtn.textContent = L.replaceBtn;\n const replaceAllBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary an-fr-replace-btn' });\n replaceAllBtn.textContent = L.replaceAllBtn;\n replaceRow.append(replaceInput, replaceBtn, replaceAllBtn);\n box.appendChild(replaceRow);\n\n // Compat div — _updateMode toggles this; kept empty so existing logic works\n const replaceActions = createElement('div', { class: 'an-fr-replace-actions' });\n replaceActions.style.display = 'none';\n box.appendChild(replaceActions);\n\n overlay.appendChild(box);\n makeDraggable(header, 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(caseBtn, 'click', () => {\n this._caseSensitive = !this._caseSensitive;\n caseCheckbox.checked = this._caseSensitive;\n caseBtn.classList.toggle('an-fr-icon-btn--active', this._caseSensitive);\n this._onSearch();\n });\n // Hidden checkbox change handler keeps backward-compat with programmatic toggles\n const d5 = on(caseCheckbox, 'change', () => {\n this._caseSensitive = caseCheckbox.checked;\n caseBtn.classList.toggle('an-fr-icon-btn--active', this._caseSensitive);\n this._onSearch();\n });\n const d6 = on(nextBtn, 'click', () => this._next());\n const d7 = on(prevBtn, 'click', () => this._prev());\n const d8 = on(replaceBtn, 'click', () => this._replace());\n const d9 = on(replaceAllBtn, 'click', () => this._replaceAll());\n const d10 = on(findInput, 'keydown', (e) => {\n const ke = /** @type {KeyboardEvent} */ (e);\n if (ke.key === 'Enter') {\n e.preventDefault();\n ke.shiftKey ? this._prev() : this._next();\n }\n });\n const d11 = on(replaceInput, 'keydown', (e) => {\n if (/** @type {KeyboardEvent} */ (e).key === 'Enter') {\n e.preventDefault();\n this._replace();\n }\n });\n const dRegex = on(regexBtn, 'click', () => {\n this._useRegex = !this._useRegex;\n regexBtn.classList.toggle('an-fr-icon-btn--active', this._useRegex);\n this._queryRegex = null; // force recompile\n this._lastQuery = null;\n this._onSearch();\n });\n const dWholeWord = on(wholeWordBtn, 'click', () => {\n this._wholeWord = !this._wholeWord;\n wholeWordBtn.classList.toggle('an-fr-icon-btn--active', this._wholeWord);\n this._queryRegex = null;\n this._lastQuery = null;\n this._onSearch();\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, dRegex, dWholeWord);\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 // 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 void _; // surroundContents fails when the range crosses element boundaries\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 this._currentIndex = 0;\n if (this._matches.length === 0) return;\n\n // Highlight the first (current) match\n if (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, case-sensitivity, regex mode, and whole-word haven't changed\n if (this._lastQuery !== query || this._lastCaseSensitive !== this._caseSensitive || this._lastUseRegex !== this._useRegex || this._lastWholeWord !== this._wholeWord) {\n const flags = this._caseSensitive ? 'g' : 'gi';\n try {\n let pattern = this._useRegex\n ? query\n : query.replace(/[.*+?^${}()|[\\]\\\\]/g, String.raw`\\$&`);\n if (this._wholeWord) pattern = `\\\\b${pattern}\\\\b`;\n this._queryRegex = new RegExp(pattern, flags);\n } catch (_) {\n this._queryRegex = null;\n }\n this._lastQuery = query;\n this._lastCaseSensitive = this._caseSensitive;\n this._lastUseRegex = this._useRegex;\n this._lastWholeWord = this._wholeWord;\n }\n if (!this._queryRegex) return results;\n const re = this._queryRegex;\n\n // Cap results to prevent blocking the main thread on very large documents\n const MAX_RESULTS = 500;\n const walker = document.createTreeWalker(root, 0x4 /* NodeFilter.SHOW_TEXT */);\n let node = walker.nextNode();\n while (node && results.length < MAX_RESULTS) {\n re.lastIndex = 0;\n let m;\n while ((m = re.exec(/** @type {Text} */ (node).textContent)) !== null && results.length < MAX_RESULTS) {\n results.push({ node: /** @type {Text} */ (node), start: m.index, end: m.index + m[0].length });\n }\n node = walker.nextNode();\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?.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?.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 match.mark.remove();\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?.parentNode) return;\n const textNode = document.createTextNode(replacement);\n mark.parentNode.insertBefore(textNode, mark);\n mark.remove();\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 mark.remove();\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 ? this.context.locale.findReplace.noResults : '';\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 if (!ctx) { resolve(null); return; } // GPU memory limit — let _confirm() handle null\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 void _; // canvas tainted — resolve with null\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(globalThis.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 on(h, 'touchstart', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const te = /** @type {TouchEvent} */ (e); this._startHandleDrag({ clientX: te.touches[0].clientX, clientY: te.touches[0].clientY }, id);\n }, { passive: false }),\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 if (/** @type {Element} */ (e.target).classList.contains('an-crop-handle')) return;\n if (e.target !== cropBox && e.target !== grid) return;\n e.preventDefault();\n e.stopPropagation();\n this._startBoxMove(e);\n }),\n on(cropBox, 'touchstart', (e) => {\n if (/** @type {Element} */ (e.target).classList.contains('an-crop-handle')) return;\n if (e.target !== cropBox && e.target !== grid) return;\n e.preventDefault();\n e.stopPropagation();\n const te2 = /** @type {TouchEvent} */ (e); this._startBoxMove({ clientX: te2.touches[0].clientX, clientY: te2.touches[0].clientY });\n }, { passive: false }),\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 = globalThis.innerWidth;\n const vh = globalThis.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 > globalThis.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?.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 this._dragDisposers?.();\n const onTouchMove = (e) => {\n e.preventDefault();\n const te3 = /** @type {TouchEvent} */ (e); onMove(/** @type {MouseEvent} */ (/** @type {unknown} */ ({ clientX: te3.touches[0].clientX, clientY: te3.touches[0].clientY })));\n };\n const cleanup = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', cleanup);\n document.removeEventListener('touchmove', onTouchMove);\n document.removeEventListener('touchend', cleanup);\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n this._dragDisposers = null;\n };\n this._dragDisposers = cleanup;\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', cleanup, { once: true });\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', 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 = /** @type {DOMRect} */ (/** @type {unknown} */ ({ 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 this._showCropError(\n 'Cannot crop this image: the image server does not allow cross-origin access. ' +\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 = /^data:image\\/(jpe?g)/i.exec(img.src) ? '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 * Show a non-blocking inline error banner appended to document.body.\n * Auto-dismisses after 4 seconds.\n * @param {string} msg\n */\n _showCropError(msg) {\n const banner = document.createElement('div');\n banner.setAttribute('role', 'alert');\n banner.style.cssText = [\n 'position:fixed', 'bottom:24px', 'left:50%', 'transform:translateX(-50%)',\n 'z-index:10200', 'max-width:420px', 'width:max-content',\n 'background:#7f1d1d', 'color:#fecaca', 'border:1px solid #b91c1c',\n 'border-radius:8px', 'padding:12px 18px',\n 'font:13px/1.5 system-ui,sans-serif',\n 'box-shadow:0 4px 16px rgba(0,0,0,.4)',\n 'pointer-events:auto',\n ].join(';');\n banner.textContent = msg;\n document.body.appendChild(banner);\n setTimeout(() => { banner.remove(); }, 4000);\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._dragDisposers?.();\n this._dragDisposers = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n [this._scrim, this._cropBox, this._toolbar].forEach((el) => {\n el?.remove();\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 globalThis. 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 void _;\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 (_) { void _; }\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 (_) { void _; }\n this._removeBanner();\n }\n\n _removeBanner() {\n this._banner?.remove();\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 = globalThis.getSelection();\n if (!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 = globalThis.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 = re.exec(text);\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 = globalThis.getSelection();\n if (!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.toggleChecklist');\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 = globalThis.getSelection();\n if (!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 = re.exec(upToCursor);\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 /** @type {ChildNode} */ (node).before(beforeNode, el, afterNode);\n /** @type {ChildNode} */ (node).remove();\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', 'hiliteColor', 'removeFormat', 'inlineCode'.\n * Any name not found in the built-in map is silently ignored.\n */\n\nimport { on } from '../core/dom.js';\n\nconst COLOR_PRESETS = [\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\n];\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 hiliteColor: _svg('<path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\"/>'),\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\n// Color buttons are handled via _openColorPicker; not in _ACTIONS.\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 removeFormat: (ctx) => {\n const editable = ctx.layoutInfo?.editable;\n if (!editable) return;\n editable.focus();\n document.execCommand('removeFormat');\n // Also strip inline style attributes which execCommand('removeFormat') misses\n const sel = globalThis.getSelection();\n if (sel?.rangeCount > 0 && !sel.getRangeAt(0).collapsed) {\n const range = sel.getRangeAt(0);\n const ancestor = range.commonAncestorContainer;\n const root = /** @type {Element|null} */ (ancestor.nodeType === 1 ? ancestor : ancestor.parentElement);\n if (root) {\n const candidates = [root, ...root.querySelectorAll('[style]')];\n for (const el of candidates) {\n if (el.hasAttribute('style') && range.intersectsNode(el)) {\n el.removeAttribute('style');\n }\n }\n }\n }\n ctx.invoke('editor.afterCommand');\n },\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\nconst _COLOR_TYPES = { foreColor: true, hiliteColor: true };\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 /** @type {HTMLElement|null} */\n this._picker = null;\n this._pickerType = null; // 'foreColor' | 'hiliteColor'\n this._savedRange = 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 this._buildColorPicker();\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 const d7 = on(globalThis, 'scroll', () => this._hide(), { passive: true });\n const d8 = on(globalThis, 'resize', () => this._hide(), { passive: true });\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8);\n return this;\n }\n\n destroy() {\n this._el?.remove();\n this._el = null;\n this._picker?.remove();\n this._picker = 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', 'hiliteColor', 'removeFormat'];\n for (const name of items) {\n if (!_ICONS[name]) continue;\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.dataset.name = name;\n btn.setAttribute('aria-label', name);\n\n if (_COLOR_TYPES[name]) {\n // Color button: SVG icon stacked above a colored strip, matching ContextMenu style\n btn.className = 'an-bubble-btn an-bubble-btn--color';\n const iconWrap = document.createElement('span');\n iconWrap.className = 'an-bubble-btn-svg';\n iconWrap.innerHTML = _ICONS[name];\n const strip = document.createElement('span');\n strip.className = 'an-bubble-color-strip';\n strip.style.background = name === 'foreColor' ? '#000000' : 'transparent';\n btn.appendChild(iconWrap);\n btn.appendChild(strip);\n } else {\n btn.className = 'an-bubble-btn';\n btn.innerHTML = _ICONS[name];\n }\n\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\n // Color buttons: save selection and open the picker\n if (_COLOR_TYPES[name]) {\n this._openColorPicker(name, btn);\n return;\n }\n\n this.context.invoke('editor.focus');\n if (_ACTIONS[name]) _ACTIONS[name](this.context);\n this._syncActive();\n });\n el.appendChild(btn);\n }\n\n document.body.appendChild(el);\n this._el = el;\n // Cache button references once — avoids querySelectorAll on every selectionchange\n this._btnCache = Array.from(el.querySelectorAll('.an-bubble-btn'));\n }\n\n _buildColorPicker() {\n const picker = document.createElement('div');\n picker.className = 'an-bubble-color-picker';\n picker.style.display = 'none';\n\n // Prevent any mousedown inside the picker from collapsing the editor selection\n picker.addEventListener('mousedown', (e) => e.preventDefault());\n\n const palette = document.createElement('div');\n palette.className = 'an-context-color-palette';\n\n COLOR_PRESETS.forEach((color) => {\n const sw = document.createElement('div');\n sw.className = 'an-context-color-swatch';\n sw.title = color;\n sw.style.background = color;\n sw.setAttribute('role', 'button');\n sw.setAttribute('aria-label', color);\n sw.addEventListener('click', (e) => {\n e.stopPropagation();\n this._applyColor(this._pickerType, color);\n });\n palette.appendChild(sw);\n });\n\n // \"No highlight\" swatch — only shown for hiliteColor\n const noColorBtn = document.createElement('div');\n noColorBtn.className = 'an-context-color-swatch an-context-color-none';\n noColorBtn.title = 'No highlight';\n noColorBtn.setAttribute('role', 'button');\n noColorBtn.setAttribute('aria-label', 'No highlight');\n noColorBtn.innerHTML = `<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 noColorBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this._applyColor('hiliteColor', 'transparent');\n });\n\n // Custom color input row\n const customRow = document.createElement('div');\n customRow.className = 'an-context-color-custom';\n const colorInput = document.createElement('input');\n colorInput.type = 'color';\n colorInput.value = '#000000';\n colorInput.title = 'Custom color';\n // stopPropagation so the picker's mousedown-preventDefault doesn't block the native color dialog\n colorInput.addEventListener('mousedown', (e) => e.stopPropagation());\n colorInput.addEventListener('change', () => {\n this._applyColor(this._pickerType, colorInput.value);\n });\n const customLabel = document.createElement('span');\n customLabel.textContent = 'Custom…';\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n\n picker.appendChild(palette);\n picker.appendChild(customRow);\n document.body.appendChild(picker);\n\n this._picker = picker;\n const pickerAny = /** @type {any} */ (picker);\n pickerAny._paletteEl = palette;\n pickerAny._noColorBtn = noColorBtn;\n pickerAny._colorInput = colorInput;\n }\n\n _openColorPicker(type, anchorBtn) {\n // Save current selection before the picker might shift focus\n const sel = globalThis.getSelection();\n if (sel?.rangeCount > 0) {\n this._savedRange = sel.getRangeAt(0).cloneRange();\n }\n\n this._pickerType = type;\n\n // Toggle \"No highlight\" swatch based on type\n const pickerAny = /** @type {any} */ (this._picker);\n const palette = pickerAny._paletteEl;\n const noColorBtn = pickerAny._noColorBtn;\n if (type === 'hiliteColor') {\n if (!palette.contains(noColorBtn)) palette.appendChild(noColorBtn);\n } else if (palette.contains(noColorBtn)) {\n noColorBtn.remove();\n }\n\n // Seed the custom color input\n /** @type {any} */ (this._picker)._colorInput.value = type === 'foreColor' ? '#000000' : '#ffff00';\n\n // Position the picker above the bubble toolbar (not blocking the content below it).\n // Fall back to below the toolbar if there's not enough room above.\n this._picker.style.display = 'block';\n const pw = this._picker.offsetWidth;\n const ph = this._picker.offsetHeight;\n const toolbarRect = this._el.getBoundingClientRect();\n\n let top = toolbarRect.top - ph - 6;\n if (top < 8) top = toolbarRect.bottom + 6;\n\n // Align horizontally with the clicked button, clamped to viewport\n const btnRect = anchorBtn.getBoundingClientRect();\n let left = btnRect.left;\n left = Math.max(8, Math.min(left, globalThis.innerWidth - pw - 8));\n\n this._picker.style.left = `${left}px`;\n this._picker.style.top = `${top}px`;\n }\n\n _closeColorPicker() {\n if (this._picker) this._picker.style.display = 'none';\n this._pickerType = null;\n }\n\n /** Restore the saved selection, apply execCommand, update the color strip, then close the picker. */\n _applyColor(type, color) {\n const editable = this.context.layoutInfo?.editable;\n if (!editable || !this._savedRange) return;\n\n editable.focus();\n const sel = globalThis.getSelection();\n sel.removeAllRanges();\n try { sel.addRange(this._savedRange.cloneRange()); } catch (_) { void _; return; }\n\n // Firefox does not support 'hiliteColor'; fall back to 'backColor'\n const cmd = type === 'hiliteColor' ? 'hiliteColor' : type;\n if (!document.execCommand(cmd, false, color) && cmd === 'hiliteColor') {\n document.execCommand('backColor', false, color);\n }\n this.context.invoke('editor.afterCommand');\n\n // Update the color strip on the corresponding button\n const name = type === 'hiliteColor' ? 'hiliteColor' : 'foreColor';\n const btn = this._el?.querySelector(`[data-name=\"${name}\"]`);\n const strip = btn?.querySelector('.an-bubble-color-strip');\n if (strip) /** @type {HTMLElement} */ (strip).style.background = color === 'transparent' ? 'transparent' : color;\n\n this._closeColorPicker();\n this._syncActive();\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, globalThis.innerWidth - bw - 8));\n\n if (top < 8) {\n top = rect.bottom + gap;\n }\n\n // If the Table Tooltip is visible, avoid overlapping it by flipping below the selection.\n // The Table Tooltip sits above the table, which is the same vertical zone the bubble\n // toolbar would normally occupy when text is selected inside a table cell.\n const tableTooltipEl = document.querySelector('.an-table-tooltip');\n if (tableTooltipEl && /** @type {HTMLElement} */ (tableTooltipEl).style.display !== 'none') {\n const ttRect = tableTooltipEl.getBoundingClientRect();\n const overlapsVertically = top < ttRect.bottom + gap && top + bh > ttRect.top - gap;\n if (overlapsVertically) {\n top = rect.bottom + gap;\n if (top + bh > globalThis.innerHeight - 8) top = ttRect.bottom + gap;\n }\n }\n\n el.style.top = `${top}px`;\n el.style.left = `${left}px`;\n el.style.visibility = '';\n\n this._syncActive();\n this._syncColorStrips();\n this._visible = true;\n }\n\n _hide() {\n if (!this._el) return;\n this._el.style.display = 'none';\n this._visible = false;\n this._closeColorPicker();\n }\n\n _syncActive() {\n if (!this._btnCache) return;\n this._btnCache.forEach((btn) => {\n const activeFn = _ACTIVE[/** @type {HTMLElement} */ (btn).dataset.name];\n btn.classList.toggle('an-active', !!(activeFn?.()));\n });\n }\n\n /** Read the current selection's color and update the color-strip indicators. */\n _syncColorStrips() {\n if (!this._el) return;\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return;\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node) return;\n const cs = globalThis.getComputedStyle(/** @type {Element} */ (node));\n\n const foreBtn = this._el.querySelector('[data-name=\"foreColor\"]');\n const foreStrip = foreBtn?.querySelector('.an-bubble-color-strip');\n if (foreStrip) /** @type {HTMLElement} */ (foreStrip).style.background = cs.color || '#000000';\n\n const hiliteBtn = this._el.querySelector('[data-name=\"hiliteColor\"]');\n const hiliteStrip = hiliteBtn?.querySelector('.an-bubble-color-strip');\n if (hiliteStrip) {\n const bg = cs.backgroundColor;\n /** @type {HTMLElement} */ (hiliteStrip).style.background = (!bg || bg === 'rgba(0, 0, 0, 0)' || bg === 'transparent') ? 'transparent' : bg;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n _onSelectionChange() {\n cancelAnimationFrame(this._rafId);\n this._rafId = requestAnimationFrame(() => {\n if (this._contextMenuOpen) return;\n // Keep toolbar visible while color picker is open\n if (this._picker && this._picker.style.display !== 'none') return;\n\n const sel = globalThis.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 in read-only mode\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, the bubble toolbar, and the color picker\n if (!this._visible) return;\n if (this._el?.contains(e.target)) return;\n if (this._picker?.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') {\n if (this._picker && this._picker.style.display !== 'none') {\n this._closeColorPicker();\n } else if (this._visible) {\n this._hide();\n }\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 * onError: (err: Error) => void,\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 onError: cfg.onError || 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 this._dropdown?.remove();\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\n // Event delegation: single listeners on the container instead of per-item\n el.addEventListener('mousedown', (e) => e.preventDefault());\n el.addEventListener('click', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-mention-item'));\n if (item) this._select(+item.dataset.index);\n });\n el.addEventListener('mousemove', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-mention-item'));\n if (item) this._highlightItem(+item.dataset.index);\n });\n\n document.body.appendChild(el);\n this._dropdown = el;\n }\n\n _renderItems(items) {\n const dd = this._dropdown;\n this._items = items.slice(0, this._cfg.maxResults);\n this._activeIndex = this._items.length > 0 ? 0 : -1;\n\n // Build all items in a DocumentFragment — one batch DOM insertion\n const frag = document.createDocumentFragment();\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 = String(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 frag.appendChild(li);\n });\n\n dd.innerHTML = ''; // one clear\n dd.appendChild(frag); // one batch insert\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 > globalThis.innerHeight) {\n top = rect.top - ddh - 4;\n }\n left = Math.max(8, Math.min(left, globalThis.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?.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 (_) { void _; }\n }\n\n // Fallback: use getClientRects() on the current collapsed selection\n const sel = globalThis.getSelection();\n if (!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 = globalThis.getSelection();\n if (!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 const cb = (items) => {\n if (!Array.isArray(items) || items.length === 0) {\n this._hideDropdown();\n return;\n }\n this._renderItems(items);\n this._showDropdown();\n };\n let result;\n try {\n result = this._cfg.onSearch(this._query, cb);\n } catch (err) {\n this._hideDropdown();\n if (typeof this._cfg.onError === 'function') this._cfg.onError(err);\n return;\n }\n if (result && typeof result.then === 'function') {\n result.then(cb).catch((err) => {\n this._hideDropdown();\n if (typeof this._cfg.onError === 'function') this._cfg.onError(err);\n });\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?.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 = globalThis.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 + '&#8203;');\n this._hideDropdown();\n this.context.triggerEvent('change', this.context.getHTML());\n }\n}\n","/**\n * SlashMenu.js — Notion-style \"/\" command palette for quick block insertion.\n *\n * Typing \"/\" as the very first character of an otherwise-empty block opens a\n * filterable list of quick-insert commands (headings, lists, table, image, …).\n * Arrow keys navigate, Enter/Tab selects, Escape or deleting back past the\n * \"/\" closes it. Disabled via `slashMenu: false`.\n *\n * Positioning follows the same synchronous-caret-rect technique as Mention.js:\n * getBoundingClientRect() on a zero-width Range over the trigger character is\n * reliable while the triggering DOM event is still live, but often returns an\n * empty rect once deferred into a callback — so the rect is captured eagerly\n * in `_onInput`, not lazily when the menu is rendered.\n */\n\nimport { on } from '../core/dom.js';\n\nexport class SlashMenu {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n\n /** @type {HTMLElement|null} */\n this._menu = null;\n /** @type {Array<{id: string, label: string, keywords: string, run: () => void}>} */\n this._filtered = [];\n this._activeIndex = -1;\n this._open = false;\n this._query = '';\n /** @type {Text|null} */\n this._textNode = null;\n this._triggerOffset = 0;\n /** @type {DOMRect|null} */\n this._caretRect = null;\n }\n\n initialize() {\n if (this.options.slashMenu === false) return this;\n const editable = this.context.layoutInfo.editable;\n const d1 = on(editable, 'input', () => this._onInput());\n const d2 = on(editable, 'keydown', (e) => this._onKeydown(e));\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 this._menu?.remove();\n this._menu = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Command list\n // ---------------------------------------------------------------------------\n\n _commands() {\n const L = this.context.locale.slashMenu;\n const ctx = this.context;\n const builtIns = [\n { id: 'h1', label: L.heading1, keywords: 'h1 heading title', run: () => ctx.invoke('editor.formatBlock', 'h1') },\n { id: 'h2', label: L.heading2, keywords: 'h2 heading subtitle', run: () => ctx.invoke('editor.formatBlock', 'h2') },\n { id: 'h3', label: L.heading3, keywords: 'h3 heading', run: () => ctx.invoke('editor.formatBlock', 'h3') },\n { id: 'ul', label: L.bulletList, keywords: 'ul bullet list unordered', run: () => ctx.invoke('editor.insertUL') },\n { id: 'ol', label: L.numberedList, keywords: 'ol numbered list ordered', run: () => ctx.invoke('editor.insertOL') },\n { id: 'checklist', label: L.checklist, keywords: 'checklist todo checkbox task', run: () => ctx.invoke('editor.toggleChecklist') },\n { id: 'quote', label: L.blockquote, keywords: 'quote blockquote', run: () => ctx.invoke('editor.formatBlock', 'blockquote') },\n { id: 'code', label: L.codeBlock, keywords: 'code pre block', run: () => ctx.invoke('editor.formatBlock', 'pre') },\n { id: 'hr', label: L.horizontalRule, keywords: 'hr divider rule line', run: () => ctx.invoke('editor.insertHr') },\n { id: 'table', label: L.table, keywords: 'table grid', run: () => ctx.invoke('editor.insertTable', 3, 3) },\n { id: 'image', label: L.image, keywords: 'image picture photo upload', run: () => ctx.invoke('imageDialog.show') },\n ];\n const custom = (this.options.slashCommands || []).map((command) => ({\n id: command.id,\n label: command.label || command.id,\n keywords: command.keywords || '',\n run: () => command.run(ctx),\n }));\n return [...builtIns, ...custom];\n }\n\n refresh() {\n if (this._open) this._filterAndRender();\n }\n\n // ---------------------------------------------------------------------------\n // Menu DOM\n // ---------------------------------------------------------------------------\n\n _buildMenu() {\n const el = document.createElement('div');\n el.className = 'an-slash-menu';\n el.setAttribute('role', 'listbox');\n el.style.display = 'none';\n\n el.addEventListener('mousedown', (e) => e.preventDefault());\n el.addEventListener('click', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-slash-menu-item'));\n if (item) this._select(+item.dataset.index);\n });\n el.addEventListener('mousemove', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-slash-menu-item'));\n if (item) this._highlight(+item.dataset.index);\n });\n\n document.body.appendChild(el);\n this._menu = el;\n return el;\n }\n\n _renderItems() {\n if (!this._menu) this._buildMenu();\n const menu = this._menu;\n const L = this.context.locale.slashMenu;\n\n if (this._filtered.length === 0) {\n menu.innerHTML = '';\n const empty = document.createElement('div');\n empty.className = 'an-slash-menu-empty';\n empty.textContent = L.noResults;\n menu.appendChild(empty);\n this._activeIndex = -1;\n return;\n }\n\n const frag = document.createDocumentFragment();\n this._filtered.forEach((item, i) => {\n const row = document.createElement('div');\n row.className = 'an-slash-menu-item';\n row.setAttribute('role', 'option');\n row.id = `an-slash-option-${item.id}`;\n row.dataset.index = String(i);\n row.textContent = item.label;\n frag.appendChild(row);\n });\n menu.innerHTML = '';\n menu.appendChild(frag);\n this._highlight(0);\n }\n\n _highlight(index) {\n if (!this._menu) return;\n this._menu.querySelectorAll('.an-slash-menu-item').forEach((el, i) => {\n const active = i === index;\n el.classList.toggle('an-slash-menu-active', active);\n el.setAttribute('aria-selected', String(active));\n if (active) this._menu.setAttribute('aria-activedescendant', el.id);\n });\n this._activeIndex = index;\n }\n\n _position() {\n const menu = this._menu;\n const rect = this._caretRect;\n if (!menu || !rect || rect.height === 0) return;\n\n menu.style.visibility = 'hidden';\n menu.style.display = 'block';\n const mh = menu.offsetHeight;\n const mw = menu.offsetWidth;\n\n let top = rect.bottom + 4;\n let left = rect.left;\n if (rect.bottom + mh + 8 > globalThis.innerHeight) {\n top = rect.top - mh - 4;\n }\n left = Math.max(8, Math.min(left, globalThis.innerWidth - mw - 8));\n\n menu.style.top = `${top}px`;\n menu.style.left = `${left}px`;\n menu.style.visibility = '';\n }\n\n _open_() {\n this._open = true;\n this._filterAndRender();\n this._position();\n }\n\n _close() {\n if (this._menu) this._menu.style.display = 'none';\n this._open = false;\n this._filtered = [];\n this._activeIndex = -1;\n this._menu?.removeAttribute('aria-activedescendant');\n this._textNode = null;\n this._caretRect = null;\n this._query = '';\n }\n\n // ---------------------------------------------------------------------------\n // Trigger detection\n // ---------------------------------------------------------------------------\n\n _isBlock(node) {\n if (node.nodeType !== Node.ELEMENT_NODE) return false;\n const display = globalThis.getComputedStyle(node).display;\n return display === 'block' || display === 'list-item' || display === 'table-cell';\n }\n\n /**\n * Detects a \"/\" trigger at the caret, requiring it to be the only content\n * typed so far in its block (i.e. the block's text is exactly \"/\" + query,\n * nothing before or after). This deliberately avoids firing mid-sentence\n * (e.g. \"10/20\", \"and/or\").\n * @returns {{ query: string, textNode: Text, triggerOffset: number } | null}\n */\n _getTriggerContext() {\n const sel = globalThis.getSelection();\n if (!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 if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;\n\n let block = range.startContainer.parentNode;\n while (block && block !== editable && !this._isBlock(block)) block = block.parentNode;\n if (!block || block === editable) return null;\n\n const fullText = block.textContent || '';\n const beforeRange = document.createRange();\n beforeRange.setStart(block, 0);\n beforeRange.setEnd(range.startContainer, range.startOffset);\n const before = beforeRange.toString();\n\n const m = /^\\/(\\S*)$/.exec(before);\n if (!m) return null;\n if (fullText.length > before.length) return null; // content after the caret\n\n return {\n query: m[1],\n textNode: /** @type {Text} */ (range.startContainer),\n triggerOffset: range.startOffset - m[0].length,\n };\n }\n\n /**\n * Captures the caret rect synchronously — see file header for why this\n * can't be deferred to a later tick.\n */\n _captureCaretRect(textNode, triggerOffset) {\n try {\n const r = document.createRange();\n const end = Math.min(triggerOffset + 1, textNode.textContent.length);\n r.setStart(textNode, triggerOffset);\n r.setEnd(textNode, end);\n const candidate = r.getBoundingClientRect();\n if (candidate.height > 0) return candidate;\n } catch (_) { void _; }\n\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return null;\n const rects = sel.getRangeAt(0).getClientRects();\n return rects.length > 0 ? rects[rects.length - 1] : null;\n }\n\n _filterAndRender() {\n const q = this._query.toLowerCase();\n this._filtered = q\n ? this._commands().filter((c) => c.keywords.includes(q) || c.label.toLowerCase().includes(q))\n : this._commands();\n this._renderItems();\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n _onInput() {\n const ctx = this._getTriggerContext();\n if (!ctx) {\n if (this._open) this._close();\n return;\n }\n\n this._textNode = ctx.textNode;\n this._triggerOffset = ctx.triggerOffset;\n this._query = ctx.query;\n this._caretRect = this._captureCaretRect(ctx.textNode, ctx.triggerOffset);\n\n if (!this._open) this._open_();\n else { this._filterAndRender(); this._position(); }\n }\n\n _onKeydown(e) {\n if (!this._open) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (this._filtered.length === 0) return;\n this._highlight((this._activeIndex + 1) % this._filtered.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (this._filtered.length === 0) return;\n this._highlight((this._activeIndex - 1 + this._filtered.length) % this._filtered.length);\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 e.preventDefault();\n this._close();\n }\n }\n\n _onDocClick(e) {\n if (!this._open) return;\n if (this._menu?.contains(e.target)) return;\n this._close();\n }\n\n // ---------------------------------------------------------------------------\n // Selection\n // ---------------------------------------------------------------------------\n\n _deleteTriggerText() {\n const node = this._textNode;\n if (!node?.isConnected) return;\n const before = node.textContent.slice(0, this._triggerOffset);\n const after = node.textContent.slice(this._triggerOffset + 1 + this._query.length);\n node.textContent = before + after;\n\n const sel = globalThis.getSelection();\n if (!sel) return;\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 _makeTriggerRemover() {\n const node = this._textNode;\n const triggerOffset = this._triggerOffset;\n const query = this._query;\n return () => {\n if (!node?.isConnected) return;\n const before = node.textContent.slice(0, triggerOffset);\n const after = node.textContent.slice(triggerOffset + 1 + query.length);\n node.textContent = before + after;\n\n const sel = globalThis.getSelection();\n if (!sel) return;\n const range = document.createRange();\n range.setStart(node, triggerOffset);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n };\n }\n\n _select(index) {\n const item = this._filtered[index];\n if (!item) return;\n\n if (item.id === 'image') {\n const beforeInsert = this._makeTriggerRemover();\n this._close();\n this.context.invoke('imageDialog.show', { beforeInsert });\n return;\n }\n\n this._deleteTriggerText();\n this._close();\n // Editor.* methods invoked by commands already call afterCommand()\n // internally (toolbar/statusbar refresh + debounced undo snapshot + the\n // 'change' event), so no manual triggerEvent here — see Editor.js.\n item.run();\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 { registerButton } from './module/Buttons.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';\nimport { SlashMenu } from './module/SlashMenu.js';\n\n/** Module registry shared across all Context instances (populated via AutumnNote.registerModule). */\nexport const _customModules = new Map();\n\n/**\n * Modules whose registration depends on an option value. Declared once so the\n * initial mount (`_registerModules`) and runtime toggles (`updateOptions`) can\n * never drift apart — previously `updateOptions({ bubbleToolbar: true })`\n * changed the option but silently left the module unregistered.\n * @type {Array<{ name: string, Class: new (ctx: Context) => { initialize: () => any, destroy?: () => void }, enabled: (options: any) => boolean }>}\n */\nconst OPTIONAL_MODULES = [\n { name: 'autoSaveRestore', Class: AutoSaveRestore, enabled: (o) => !!o.autoSaveRestore },\n { name: 'markdownShortcuts', Class: MarkdownShortcuts, enabled: (o) => o.markdownShortcuts !== false },\n { name: 'bubbleToolbar', Class: BubbleToolbar, enabled: (o) => !!o.bubbleToolbar },\n { name: 'mention', Class: Mention, enabled: (o) => !!o.mention },\n { name: 'slashMenu', Class: SlashMenu, enabled: (o) => o.slashMenu !== false },\n];\n\n/** Global plugin registry (populated via AutumnNote.use()). Applied to every new Context. */\nexport const _globalPlugins = 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 = /** @type {any} */ ({});\n\n /** @type {Map<string, Function[]>} */\n this._listeners = new Map();\n\n /** @type {Map<string, object>} */\n this._modules = new Map();\n\n /** @type {Map<string, { plugin: object, publicApi: * }>} */\n this._plugins = new Map();\n\n this._disposers = [];\n this._alive = false;\n this._autoSaveTimer = null;\n this._pendingAutoSave = null;\n this._suppressedRemoteHTML = null;\n /** @type {Promise<void>|null} Settles when destroy()'s closing auto-save finishes */\n this._destroyPromise = null;\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?.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?.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 // Apply plugins registered globally via AutumnNote.use()\n this._applyGlobalPlugins();\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 for (const { name, Class, enabled } of OPTIONAL_MODULES) {\n if (enabled(this.options)) register(name, Class);\n }\n\n // Custom modules registered via AutumnNote.registerModule()\n if (_customModules.size > 0) {\n for (const [name, ModuleClass] of _customModules) {\n register(name, ModuleClass);\n }\n }\n }\n\n /**\n * Registers or tears down option-gated modules so they match the current\n * option values. Called after `updateOptions()` so toggling e.g.\n * `bubbleToolbar` at runtime actually takes effect.\n */\n _syncOptionalModules() {\n for (const { name, Class, enabled } of OPTIONAL_MODULES) {\n const shouldRun = enabled(this.options);\n const isRunning = this._modules.has(name);\n if (shouldRun === isRunning) continue;\n\n if (shouldRun) {\n const instance = new Class(this);\n this._modules.set(name, instance);\n instance.initialize();\n } else {\n const instance = this._modules.get(name);\n if (typeof instance?.destroy === 'function') instance.destroy();\n this._modules.delete(name);\n }\n }\n }\n\n /**\n * Registers and initialises a custom module on this instance.\n * @param {string} name\n * @param {new (ctx: this) => any} 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 registerSlashCommand(command) {\n if (!command?.id || typeof command.run !== 'function') {\n throw new TypeError('[AutumnNote] Slash command requires an id and run(context) function.');\n }\n const commands = this.options.slashCommands || (this.options.slashCommands = []);\n const index = commands.findIndex((item) => item.id === command.id);\n if (index >= 0) commands[index] = command;\n else commands.push(command);\n this.invoke('slashMenu.refresh');\n return this;\n }\n\n /**\n * Installs a plugin on this editor instance.\n * If called after create(), buttons are registered immediately but the toolbar\n * must be rebuilt via ctx.invoke('toolbar.rebuild') to render new buttons.\n * @param {object} plugin - { name, version?, buttons?, install?, uninstall? }\n * @param {object} [options] - Forwarded to plugin.install(context, options)\n * @returns {this}\n */\n use(plugin, options = {}) {\n if (Array.isArray(plugin.buttons)) {\n plugin.buttons.forEach((b) => registerButton(b));\n }\n this._installPlugin(plugin, options);\n return this;\n }\n\n /**\n * Returns the public API returned by plugin.install(), or null.\n * @param {string} name\n * @returns {*}\n */\n getPlugin(name) {\n return this._plugins.get(name)?.publicApi ?? null;\n }\n\n _installPlugin(plugin, pluginOptions = {}) {\n const { name } = plugin;\n if (!name || typeof name !== 'string') {\n console.warn('[AutumnNote] Plugin must have a string `name` property.');\n return;\n }\n if (this._plugins.has(name)) {\n console.warn(`[AutumnNote] Plugin \"${name}\" already installed on this instance. Skipping.`);\n return;\n }\n const publicApi = (typeof plugin.install === 'function')\n ? plugin.install(this, pluginOptions) ?? null\n : null;\n this._plugins.set(name, { plugin, publicApi });\n }\n\n _applyGlobalPlugins() {\n if (_globalPlugins.size === 0) return;\n for (const { plugin, options } of _globalPlugins.values()) {\n this._installPlugin(plugin, options);\n }\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', (html) => this._syncToTarget(html));\n const dRemote = this.on('change', (html) => {\n if (this.options.blockIds) { this.ensureBlockIds(); html = this.getHTML(); }\n if (html === this._suppressedRemoteHTML) { this._suppressedRemoteHTML = null; return; }\n this.options.collaborationAdapter?.onLocalChange?.(html, this);\n });\n this._disposers.push(d0, d1, d2, d3, dRemote);\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', (html) => this._scheduleAutoSave(html));\n this._disposers.push(d4);\n }\n }\n\n _scheduleAutoSave(html) {\n this._pendingAutoSave = html;\n clearTimeout(this._autoSaveTimer);\n this._autoSaveTimer = setTimeout(() => this.flushAutoSave(), this.options.autoSaveDelay ?? 400);\n }\n\n async flushAutoSave() {\n clearTimeout(this._autoSaveTimer);\n this._autoSaveTimer = null;\n if (this._pendingAutoSave == null) return;\n const html = this._pendingAutoSave;\n this._pendingAutoSave = null;\n const key = this.options.autoSaveKey;\n const savedAt = Date.now();\n try {\n const adapter = this.options.autoSaveAdapter;\n if (typeof adapter?.save === 'function') {\n await adapter.save({ key, html, savedAt, context: this });\n } else {\n localStorage.setItem(key, html);\n localStorage.setItem(key + ':asrmeta', JSON.stringify({ savedAt }));\n }\n this.triggerEvent('autoSave', { key, html, savedAt });\n } catch (error) {\n this.triggerEvent('autoSaveError', { key, error });\n }\n }\n\n async loadAutoSave() {\n const adapter = this.options.autoSaveAdapter;\n if (typeof adapter?.load === 'function') {\n return adapter.load({ key: this.options.autoSaveKey, context: this });\n }\n try { return localStorage.getItem(this.options.autoSaveKey); } catch (_) { return null; }\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 /** Updates runtime-safe options without recreating the editor. */\n updateOptions(overrides = {}) {\n const next = mergeDeep(this.options, overrides);\n Object.keys(this.options).forEach((key) => delete this.options[key]);\n Object.assign(this.options, next);\n\n const { container, editable } = this.layoutInfo;\n if (Object.hasOwn(overrides, 'readOnly')) this.setDisabled(Boolean(this.options.readOnly));\n if (Object.hasOwn(overrides, 'spellcheck')) editable.spellcheck = this.options.spellcheck !== false;\n if (Object.hasOwn(overrides, 'placeholder')) editable.dataset.placeholder = this.options.placeholder || '';\n if (Object.hasOwn(overrides, 'direction')) {\n const rtl = this.options.direction === 'rtl';\n editable.setAttribute('dir', rtl ? 'rtl' : 'ltr');\n container.classList.toggle('an-dir-rtl', rtl);\n }\n if (Object.hasOwn(overrides, 'height') || Object.hasOwn(overrides, 'minHeight')) {\n const height = this.options.height || this.options.minHeight || 0;\n editable.style.minHeight = height ? `${height}px` : '';\n }\n if (Object.hasOwn(overrides, 'maxHeight')) {\n editable.style.maxHeight = this.options.maxHeight ? `${this.options.maxHeight}px` : '';\n }\n if (Object.hasOwn(overrides, 'toolbar')) this.invoke('toolbar.rebuild');\n // Start/stop option-gated modules (bubbleToolbar, mention, slashMenu, ...)\n // so toggling them here behaves the same as passing them to create().\n this._syncOptionalModules();\n this.invoke('statusbar.update');\n this.triggerEvent('optionsChange', { ...overrides });\n return this;\n }\n\n /**\n * Returns the current HTML content of the editor.\n * Zero-width spaces (U+200B) inserted by inline editing helpers are stripped\n * from the output so they don't leak into the consumer's HTML.\n * @returns {string}\n */\n getHTML() {\n const html = this.invoke('editor.getHTML');\n return typeof html === 'string' ? html.replace(/​/g, '') : html;\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 the number of available undo steps.\n * @returns {number}\n */\n getUndoCount() {\n return this.invoke('editor.getUndoCount') ?? 0;\n }\n\n /**\n * Returns the number of available redo steps.\n * @returns {number}\n */\n getRedoCount() {\n return this.invoke('editor.getRedoCount') ?? 0;\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 getSelectionBookmark() {\n return this.invoke('editor.getSelectionBookmark') ?? null;\n }\n\n restoreSelectionBookmark(bookmark) {\n return this.invoke('editor.restoreSelectionBookmark', bookmark);\n }\n\n async importDocument(format, data) {\n const adapter = this.options.documentAdapters?.[format];\n let html;\n if (typeof adapter?.import === 'function') html = await adapter.import(data, this);\n else if (format === 'html') html = String(data ?? '');\n else if (format === 'markdown') { this.setMarkdown(String(data ?? '')); return this; }\n else if (format === 'text') { this.setText(String(data ?? '')); return this; }\n else throw new Error(`[AutumnNote] No importer registered for \"${format}\".`);\n this.setHTML(html);\n return this;\n }\n\n async exportDocument(format) {\n const adapter = this.options.documentAdapters?.[format];\n if (typeof adapter?.export === 'function') return adapter.export(this, this.getHTML());\n if (format === 'html') return this.getHTML();\n if (format === 'markdown') return this.getMarkdown();\n if (format === 'text') return this.getText();\n throw new Error(`[AutumnNote] No exporter registered for \"${format}\".`);\n }\n\n ensureBlockIds() {\n const blocks = this.layoutInfo.editable.children;\n for (const block of blocks) {\n if (!block.hasAttribute('data-an-block-id')) {\n const id = globalThis.crypto?.randomUUID?.() || `an-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n block.setAttribute('data-an-block-id', id);\n }\n }\n return this;\n }\n\n getDocument() {\n if (this.options.blockIds) this.ensureBlockIds();\n return { version: 1, html: this.getHTML(), markdown: this.getMarkdown() };\n }\n\n loadDocument(documentData) {\n this.setHTML(documentData?.html || '');\n this.clearHistory();\n return this;\n }\n\n applyRemoteHTML(html) {\n this.setHTML(html);\n this._suppressedRemoteHTML = this.getHTML();\n this.clearHistory();\n return this;\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 a.remove();\n URL.revokeObjectURL(url);\n }\n\n /**\n * Opens the editor content in a new globalThis 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, (c) => `&#${c.charCodeAt(0)};`);\n const markup = '<!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 const blob = new Blob([markup], { type: 'text/html' });\n const url = URL.createObjectURL(blob);\n const w = globalThis.open(url, '_blank');\n if (!w) { URL.revokeObjectURL(url); return; } // popup blocked by browser\n w.addEventListener('load', () => {\n w.print();\n URL.revokeObjectURL(url);\n });\n }\n\n /**\n * Returns an array of heading objects representing the table of contents.\n * Each entry has: level (1-6), text (heading text), element (DOM element).\n * @returns {{ level: number, text: string, element: HTMLElement }[]}\n */\n getTableOfContents() {\n const headings = Array.from(\n this.layoutInfo.editable.querySelectorAll('h1,h2,h3,h4,h5,h6')\n );\n return headings.map((el) => ({\n level: parseInt(el.tagName[1], 10),\n text: el.textContent?.trim() ?? '',\n element: /** @type {HTMLElement} */ (el),\n }));\n }\n\n /**\n * Moves focus into the editable area.\n */\n focus() {\n this.layoutInfo.editable.focus();\n }\n\n /**\n * Removes focus from the editable area.\n */\n blur() {\n this.layoutInfo.editable.blur();\n }\n\n /**\n * Returns true when the editor is currently in fullscreen mode.\n * @returns {boolean}\n */\n isFullscreen() {\n return this.invoke('fullscreen.isActive') === true;\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 * Teardown itself is synchronous; the returned promise only settles once the\n * closing auto-save has finished, so `await editor.destroy()` is worth doing\n * when using an async `autoSaveAdapter`. Ignoring the return value is safe.\n * @returns {Promise<void>}\n */\n destroy() {\n if (!this._alive) return this._destroyPromise ?? Promise.resolve();\n\n // Start the final auto-save before tearing anything down. `_listeners` is\n // deliberately kept alive until this settles, otherwise the closing\n // autoSave/autoSaveError event fires into an already-cleared listener map\n // and an async adapter's last write completes silently.\n const pendingFlush = this._pendingAutoSave != null\n ? this.flushAutoSave().catch(() => {})\n : null;\n\n this._modules.forEach((module) => {\n if (typeof module.destroy === 'function') module.destroy();\n });\n this._modules.clear();\n\n for (const { plugin } of this._plugins.values()) {\n if (typeof plugin.uninstall === 'function') {\n try { plugin.uninstall(this); } catch (_) { void _; }\n }\n }\n this._plugins.clear();\n\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n const container = this.layoutInfo.container;\n const wasDark = container?.classList.contains('an-theme-dark');\n const wasAuto = container?.classList.contains('an-theme-auto');\n if (container?.parentNode) {\n // Restore original element\n this.targetEl.style.display = '';\n container.remove();\n }\n // Clean up body theme classes if no other editors of that type remain\n if (wasDark && !document.querySelector('.an-container.an-theme-dark')) {\n document.body.classList.remove('an-theme-dark');\n }\n if (wasAuto && !document.querySelector('.an-container.an-theme-auto')) {\n document.body.classList.remove('an-theme-auto');\n }\n\n if (typeof this.options.onDestroy === 'function') {\n this.options.onDestroy(this);\n }\n\n this._alive = false;\n\n // Resolves once the closing auto-save (if any) has finished. Callers using\n // an async autoSaveAdapter can `await editor.destroy()` to be sure the last\n // write landed before unloading.\n this._destroyPromise = Promise.resolve(pendingFlush).then(() => {\n this._listeners.clear();\n });\n return this._destroyPromise;\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Syncs editor HTML back into the original textarea/input for form submission.\n */\n _syncToTarget(html) {\n if (this.targetEl.tagName === 'TEXTAREA' || this.targetEl.tagName === 'INPUT') {\n /** @type {HTMLInputElement} */ (this.targetEl).value = typeof html === 'string' ? html : 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.flat();\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 globalThis || 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\n// @ts-ignore\nimport '../styles/autumnnote.scss';\nimport { Context, _customModules, _globalPlugins } from './Context.js';\nimport { registerButton, buttons } from './module/Buttons.js';\nimport { defaultOptions } from './settings.js';\nimport { registerLocale } from './i18n/index.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, registerLocale } 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(/** @type {HTMLElement} */ (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 /**\n * Installs a plugin globally — applied to every future editor instance.\n * Plugin `buttons` are registered to the global button registry immediately\n * so they are available when Toolbar initialises inside create().\n * Plugin `install()` is called after all built-in modules have initialised.\n * @param {object} plugin - { name, version?, buttons?, install?, uninstall? }\n * @param {object} [options] - Forwarded to plugin.install(context, options)\n * @returns {typeof AutumnNote}\n */\n use(plugin, options = {}) {\n if (!plugin || typeof plugin.name !== 'string') {\n throw new TypeError('[AutumnNote] AutumnNote.use: plugin must have a string `name` property.');\n }\n if (_globalPlugins.has(plugin.name)) {\n console.warn(`[AutumnNote] Plugin \"${plugin.name}\" already registered globally. Skipping.`);\n return this;\n }\n if (Array.isArray(plugin.buttons)) {\n plugin.buttons.forEach((b) => registerButton(b));\n }\n _globalPlugins.set(plugin.name, { plugin, options });\n return this;\n },\n\n /**\n * Returns true if a plugin with the given name has been registered globally.\n * @param {string} name\n * @returns {boolean}\n */\n hasPlugin(name) { return _globalPlugins.has(name); },\n\n /**\n * Registers a single button definition in the global button registry.\n * After create(), call ctx.invoke('toolbar.rebuild') to render new buttons.\n * @param {object} btnDef - ButtonDef-compatible object with a `name` string\n * @returns {typeof AutumnNote}\n */\n registerButton(btnDef) { registerButton(btnDef); return this; },\n\n /**\n * Registers a locale so `lang: '<code>'` can select it.\n * Only English ships in the ESM bundle — import others from\n * `autumnnote/i18n/<code>` and register them here.\n * @param {string} code\n * @param {object} locale\n */\n registerLocale(code, locale) { registerLocale(code, locale); return this; },\n\n /** Registers a slash-menu command for future editor instances. */\n registerSlashCommand(command) {\n if (!command?.id || typeof command.run !== 'function') {\n throw new TypeError('[AutumnNote] Slash command requires an id and run(context) function.');\n }\n const commands = defaultOptions.slashCommands;\n const index = commands.findIndex((item) => item.id === command.id);\n if (index >= 0) commands[index] = command;\n else commands.push(command);\n return this;\n },\n\n /** All pre-built button definitions — accessible in every module format including UMD/CJS. */\n buttons,\n\n /** Library version */\n version: '2.0.0',\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 /** @type {Element[]} */ (Array.from(selector));\n }\n return [];\n}\n\nexport default AutumnNote;\n"],"mappings":"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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","ICON_SVG","ICON_SVG","ICON_SVG","ICONS","SHOW_DELAY","HIDE_DELAY","SHOW_DELAY","HIDE_DELAY","ICONS","ICONS","ICONS","SHOW_DELAY","HIDE_DELAY","ICONS","ICONS","COLOR_PRESETS","clamp","outW","outH"],"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/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/core/detectLang.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/BaseDialog.js","../src/js/module/LinkDialog.js","../src/js/module/ImageDialog.js","../src/js/module/VideoDialog.js","../src/js/module/BaseResizer.js","../src/js/module/ImageResizer.js","../src/js/module/VideoResizer.js","../src/js/module/LinkTooltip.js","../src/js/module/BaseMediaTooltip.js","../src/js/module/ImageTooltip.js","../src/js/module/VideoTooltip.js","../src/js/module/table-icons.js","../src/js/module/table-grid.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/module/SlashMenu.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 * Create a wrapper that limits how often `fn` can be invoked while ensuring the last call in a burst is executed.\n * @param {Function} fn - Function to be throttled.\n * @param {number} limit - Time globalThis in milliseconds during which at most one call is allowed.\n * @returns {Function} A wrapper function that invokes `fn` at most once per `limit` milliseconds; calls preserve `this` and original arguments and schedule a trailing invocation for the final call in a burst.\n */\nexport function throttle(fn, limit) {\n let lastCall = -Infinity;\n let trailingTimer = null;\n return function (...args) {\n const now = performance.now();\n const elapsed = now - lastCall;\n if (elapsed >= limit) {\n lastCall = now;\n clearTimeout(trailingTimer);\n trailingTimer = null;\n return fn.apply(this, args);\n }\n // Ensure the final event in a burst is not dropped\n clearTimeout(trailingTimer);\n trailingTimer = setTimeout(() => {\n lastCall = performance.now();\n trailingTimer = null;\n fn.apply(this, args);\n }, limit - elapsed);\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: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n bottom: rect.bottom,\n right: 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?.nodeType === ELEMENT_NODE;\n/** @param {Node} node */\nexport const isText = (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) && /** @type {HTMLElement} */ (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 /** @type {Element|null} */ (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 /** @type {Element|null} */ (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?.parentNode) {\n /** @type {ChildNode} */ (node).remove();\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 /** @type {ChildNode} */ (node).remove();\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 * Determine whether a DOM node contains no visible content.\n *\n * Text nodes are considered empty when their `nodeValue` is empty. Void elements (e.g., `img`, `br`, `input`) are considered non-empty. An element with exactly one `<br>` child is treated as empty. For other elements, emptiness means trimmed `textContent` is empty and there are no descendant `img`, `video`, `hr`, or `table` elements.\n * @param {Node} node - Node to inspect for visible content.\n * @returns {boolean} `true` if the node has no visible content, `false` otherwise.\n */\nexport function isEmpty(node) {\n if (isText(node)) return !node.nodeValue;\n if (isVoid(node)) return false;\n if (node.childNodes.length === 1 && node.firstChild?.nodeName === 'BR') return true;\n return !node.textContent.trim() && !/** @type {Element} */ (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 = globalThis.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?.();\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.at(-1);\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n /** @type {HTMLElement} */ (last).focus();\n }\n } else if (document.activeElement === last) {\n e.preventDefault();\n /** @type {HTMLElement} */ (first).focus();\n }\n };\n\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n}\n\n/**\n * Makes a dialog box draggable by its handle element.\n * On first drag the box is pinned to its current viewport coordinates via\n * `position:fixed`, freeing it from the parent flex container's centering.\n * The position is clamped to the visible viewport.\n *\n * @param {HTMLElement} handle Element the user grabs (title bar / header)\n * @param {HTMLElement} box Element that actually moves\n * @returns {Function} Cleanup function (removes the mousedown listener)\n */\nexport function makeDraggable(handle, box) {\n handle.style.cursor = 'grab';\n\n const onMousedown = (e) => {\n if (e.button !== 0) return;\n // Don't start drag when clicking on interactive children of the handle\n if (/** @type {Element} */ (e.target).closest('button, input, select, textarea, a')) return;\n\n e.preventDefault();\n\n // First drag: snapshot position and pin to viewport with position:fixed\n if (!box.dataset.anDragPinned) {\n const r = box.getBoundingClientRect();\n box.style.position = 'fixed';\n box.style.margin = '0';\n box.style.left = `${r.left}px`;\n box.style.top = `${r.top}px`;\n box.dataset.anDragPinned = '1';\n }\n\n const startX = e.clientX - Number.parseFloat(box.style.left);\n const startY = e.clientY - Number.parseFloat(box.style.top);\n\n handle.style.cursor = 'grabbing';\n\n const onMove = (ev) => {\n const bw = box.offsetWidth;\n const bh = box.offsetHeight;\n box.style.left = `${Math.max(0, Math.min(ev.clientX - startX, globalThis.innerWidth - bw))}px`;\n box.style.top = `${Math.max(0, Math.min(ev.clientY - startY, globalThis.innerHeight - bh))}px`;\n };\n\n const onUp = () => {\n handle.style.cursor = 'grab';\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n };\n\n handle.addEventListener('mousedown', onMousedown);\n return () => handle.removeEventListener('mousedown', onMousedown);\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 void _e; // guard against detached nodes\n }\n return range;\n }\n\n /**\n * Select this wrapped range in the globalThis.\n */\n select() {\n const sel = globalThis.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 /** @type {Element|null} */ (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 /** @type {Element|null} */ (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 globalThis 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 = globalThis.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 = globalThis.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 = globalThis.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 = globalThis.getSelection();\n if (!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 = /** @type {Element|null} */ (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 uEl.remove();\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 = globalThis.getSelection();\n if (!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 = /** @type {Element|null} */ (sc)?.closest('s') || /** @type {Element|null} */ (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 sEl.remove();\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|Document} [editable] - scoping element to avoid touching nodes outside this editor\n */\nexport function fontSize(size, editable = document) {\n const sel = globalThis.getSelection();\n const wasCollapsed = !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?.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 (_) { void _; /* 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.remove();\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.at(-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 (_) { void _; /* 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 = globalThis.getSelection();\n if (sel?.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const checkLi = /** @type {Element|null} */ (container)?.closest('.an-checklist li');\n if (checkLi) {\n _checklistItemToP(/** @type {HTMLElement} */ (checkLi));\n return;\n }\n }\n execCommand('outdent');\n}\n\n/**\n * Convert a checklist <li> into a paragraph and move any following items into a new checklist.\n *\n * Preserves inline markup from the converted item, strips zero-width space anchors,\n * and replaces empty content with a non‑breaking space. If there are list items\n * after the converted item they are moved into a new <ul class=\"an-checklist\">\n * inserted immediately after the original list. The original <li> is removed and\n * the original list is removed if it becomes empty. Attempts to place the caret\n * at the start of the newly created <p>.\n * @param {HTMLElement} checkLi - The checklist `<li>` element to convert to a `<p>`.\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> preserving inline formatting (bold/italic/links) from the item's content\n const p = document.createElement('p');\n for (const child of checkLi.childNodes) {\n if (child.nodeType === 1 && /** @type {Element} */ (child).tagName === 'INPUT') continue;\n p.appendChild(child.cloneNode(true));\n }\n // Strip ZWS anchors left over from checklist markup\n p.innerHTML = p.innerHTML.replaceAll('\\u200B', '');\n if (!p.hasChildNodes() || !p.textContent.trim()) {\n p.innerHTML = '';\n p.appendChild(document.createTextNode('\\u00a0'));\n }\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 checkLi.remove();\n if (checkUl.children.length === 0) checkUl.remove();\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?.nodeType === 3 ? firstChild : p, 0);\n nr.collapse(true);\n const s = globalThis.getSelection();\n if (s) { s.removeAllRanges(); s.addRange(nr); }\n } catch {}\n}\n\n/**\n * Inserts an unordered (bulleted) list, or converts the current list to `<ul>`.\n *\n * When the cursor is already inside a list, direct DOM manipulation is used to\n * transition between list types — `execCommand` alone cannot handle checklist →\n * UL/OL conversions because it has no awareness of the `an-checklist` class or\n * the checkbox `<input>` elements.\n *\n * Transition paths:\n * - **Checklist → UL**: strips `an-checklist` class and all checkbox inputs;\n * converts `<ol>` container to `<ul>` via `changeTagName()` if needed.\n * - **OL → UL**: swaps the container tag via `changeTagName()`.\n * - **UL → paragraphs**: falls back to `execCommand('insertUnorderedList')`\n * which toggles the list off (browser-native behaviour).\n * - **No list → UL**: falls back to `execCommand('insertUnorderedList')`.\n */\n/**\n * Helper to get the closest ul/ol element containing the current selection.\n * @returns {Element|null}\n */\nfunction getSelectedList() {\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return null;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n return /** @type {Element|null} */ (container)?.closest('ul, ol') || null;\n}\n\n/**\n * Strips the checklist class and checkbox inputs from a list element.\n * @param {Element} listEl\n */\nfunction stripChecklist(listEl) {\n listEl.classList.remove('an-checklist');\n listEl.querySelectorAll('input[type=\"checkbox\"]').forEach(cb => cb.remove());\n}\n\nexport function insertUnorderedList() {\n const listEl = getSelectedList();\n if (listEl) {\n if (listEl.classList.contains('an-checklist')) {\n // Checklist → UL: strip checkboxes and class, swap tag if needed\n stripChecklist(listEl);\n if (listEl.tagName === 'OL') {\n changeTagName(listEl, 'ul');\n }\n } else if (listEl.tagName === 'OL') {\n // OL → UL: swap container tag\n changeTagName(listEl, 'ul');\n } else {\n // Already UL → toggle off via execCommand\n execCommand('insertUnorderedList');\n }\n } else {\n // Not in a list → create new UL via execCommand\n execCommand('insertUnorderedList');\n }\n}\n\n/**\n * Inserts an ordered (numbered) list, or converts the current list to `<ol>`.\n *\n * When the cursor is already inside a list, direct DOM manipulation is used to\n * transition between list types — `execCommand` alone cannot handle checklist →\n * UL/OL conversions because it has no awareness of the `an-checklist` class or\n * the checkbox `<input>` elements.\n *\n * Transition paths:\n * - **Checklist → OL**: strips `an-checklist` class and all checkbox inputs;\n * converts container to `<ol>` via `changeTagName()`.\n * - **UL → OL**: swaps the container tag via `changeTagName()`.\n * - **OL → paragraphs**: falls back to `execCommand('insertOrderedList')`\n * which toggles the list off (browser-native behaviour).\n * - **No list → OL**: falls back to `execCommand('insertOrderedList')`.\n */\nexport function insertOrderedList() {\n const listEl = getSelectedList();\n if (listEl) {\n if (listEl.classList.contains('an-checklist')) {\n // Checklist → OL: strip checkboxes and class, swap to <ol>\n stripChecklist(listEl);\n changeTagName(listEl, 'ol');\n } else if (listEl.tagName === 'UL') {\n // UL → OL: swap container tag\n changeTagName(listEl, 'ol');\n } else {\n // Already OL → toggle off via execCommand\n execCommand('insertOrderedList');\n }\n } else {\n // Not in a list → create new OL via execCommand\n execCommand('insertOrderedList');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Line-height helper\n// ---------------------------------------------------------------------------\n\n/**\n * Set the line-height on every block-level element that intersects the current selection.\n *\n * If the selection is collapsed, the nearest enclosing block element receives the style.\n * For a non-collapsed selection, all unique block ancestors of text nodes that intersect the range are updated;\n * if none are found, the nearest block ancestor of the range's common ancestor is updated.\n * @param {string} value - Line-height value to apply; typically a unitless multiplier (for example, \"1.5\").\n */\nexport function lineHeight(value) {\n const sel = globalThis.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.createTreeWalker(\n range.commonAncestorContainer,\n NodeFilter.SHOW_TEXT,\n { acceptNode: (node) => range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP },\n );\n let textNode;\n while ((textNode = iter.nextNode())) {\n const block = nearestBlock(textNode);\n if (block) blocks.add(block);\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 = /** @type {Element|null} */ (isElement(container) ? container : container.parentElement);\n if (!el) return {};\n\n const computed = globalThis.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 = globalThis.getSelection();\n if (!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 = /** @type {Element|null} */ (container)?.closest('code');\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 codeEl.remove();\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 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.at(-1);\n const nr = document.createRange();\n // Use the (possibly merged) live node if still in the DOM.\n const anchorNode = firstMoved.parentNode === parent\n ? firstMoved\n : (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 (_) { void _; /* 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 = globalThis.getSelection();\n if (!sel?.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n const code = /** @type {Element|null} */ (sc)?.closest('code');\n return !!(code && !code.closest('pre'));\n}\n\n// ---------------------------------------------------------------------------\n// Checklist (task list)\n// ---------------------------------------------------------------------------\n\n/**\n * Changes the tag name of an element in the DOM while preserving attributes and children.\n * @param {Element} el\n * @param {string} newTagName\n * @returns {HTMLElement}\n */\nfunction changeTagName(el, newTagName) {\n const newEl = document.createElement(newTagName);\n for (const attr of el.attributes) {\n newEl.setAttribute(attr.name, attr.value);\n }\n while (el.firstChild) {\n newEl.appendChild(el.firstChild);\n }\n el.parentNode.replaceChild(newEl, el);\n return newEl;\n}\n\n/**\n * Ensures all list items under the list element have a checkbox.\n * @param {Element} listEl\n */\nfunction ensureCheckboxes(listEl) {\n listEl.querySelectorAll('li').forEach(li => {\n const existingCb = li.querySelector('input[type=\"checkbox\"]');\n if (!existingCb) {\n const cb = document.createElement('input');\n cb.type = 'checkbox';\n cb.contentEditable = 'false';\n li.insertBefore(cb, li.firstChild);\n }\n });\n}\n\n/**\n * Toggle a checklist at the current selection or caret.\n */\nexport function toggleChecklist() {\n const sel = globalThis.getSelection();\n if (!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 listEl = /** @type {Element|null} */ (container)?.closest('ul, ol');\n if (listEl) {\n if (listEl.classList.contains('an-checklist')) {\n // Transition from Checklist to Paragraphs (Toggle off checklist entirely)\n const parent = listEl.parentNode;\n if (parent) {\n const lis = Array.from(listEl.children);\n let /** @type {HTMLParagraphElement|null} */ firstP = null;\n lis.forEach(li => {\n const p = document.createElement('p');\n for (const child of li.childNodes) {\n if (child.nodeType === 1 && /** @type {Element} */ (child).tagName === 'INPUT') continue;\n p.appendChild(child.cloneNode(true));\n }\n p.innerHTML = p.innerHTML.replaceAll('\\u200b', '').replaceAll('\\u200B', '');\n if (!p.hasChildNodes() || !p.textContent.trim()) {\n p.innerHTML = '';\n p.appendChild(document.createTextNode('\\u00a0'));\n }\n listEl.before(p);\n if (!firstP) firstP = p;\n });\n listEl.remove();\n \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 }\n } else {\n // Transition from standard UL/OL to Checklist\n const targetUl = changeTagName(listEl, 'ul');\n targetUl.classList.add('an-checklist');\n ensureCheckboxes(targetUl);\n \n // Place caret inside the first LI\n const firstLi = targetUl.querySelector('li');\n if (firstLi) {\n const nr = document.createRange();\n nr.selectNodeContents(firstLi);\n nr.collapse(false);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\n }\n } else {\n // Selection is not in a list: build the checklist directly via DOM\n // manipulation. execCommand('insertUnorderedList') is intentionally\n // avoided here — its behaviour on collapsed/empty selections and\n // non-standard blocks (e.g. <section>) is too inconsistent across\n // browsers (and a no-op in jsdom), which left toggleChecklist() as a\n // silent no-op in those cases.\n // The editable root itself is a <div> and must never be treated as a\n // \"block\" to convert/replace/remove — otherwise selections that include\n // raw text nodes sitting directly inside it (e.g. the first line typed\n // into an empty editor) would destroy the .an-editable element.\n const editableRoot = /** @type {Element|null} */ (container)?.closest('[contenteditable=\"true\"]');\n const isCollapsed = range.collapsed;\n if (isCollapsed) {\n // Find the nearest block-level ancestor (p, div, li, h1-h6, blockquote,\n // etc.) 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 = /** @type {Element|null} */ (container);\n while (block?.parentNode && block !== editableRoot && !BLOCK_TAGS.has(block.tagName)) {\n block = /** @type {Element|null} */ (block.parentNode);\n }\n if (block === editableRoot) block = null;\n // Fallback: if no block element found (e.g. cursor directly in editable\n // root), insert a fresh item with a zero-width-space so the cursor ends\n // up inside it.\n const itemText = (block && BLOCK_TAGS.has(block.tagName))\n ? Array.from(block.childNodes)\n .map((n) => n.textContent)\n .join('')\n .replaceAll('\\u00a0', ' ')\n : '';\n\n const newUl = document.createElement('ul');\n newUl.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 newUl.appendChild(li);\n\n if (block && BLOCK_TAGS.has(block.tagName)) {\n block.parentNode.replaceChild(newUl, block);\n } else {\n // Cursor directly in editable root — insert via Range API.\n const nativeRange = sel.getRangeAt(0);\n nativeRange.deleteContents();\n nativeRange.insertNode(newUl);\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 // Non-collapsed selection — convert each intersected block element into\n // a checklist item using direct DOM manipulation.\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 blockEl = /** @type {Element|null} */ (node.nodeType === Node.TEXT_NODE ? node.parentElement : node);\n while (blockEl && blockEl !== editableRoot && !BLOCK_TAGS_MULTI.has(blockEl.tagName)) {\n blockEl = blockEl.parentElement;\n }\n if (blockEl === editableRoot) blockEl = null;\n if (blockEl && !seenBlocks.has(blockEl)) {\n seenBlocks.add(blockEl);\n blocks.push(blockEl);\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 /** @type {Text|null} */ 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.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.remove());\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/**\n * Returns true when the cursor is inside a checklist item.\n * @returns {boolean}\n */\nexport function isInChecklist() {\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return false;\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n return !!(/** @type {Element|null} */ (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 {Array<string|{value:string,label:string,disabled?:boolean}>} [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 * @property {string} [selectClass] - extra CSS class(es) for the <select>\n * @property {string} [placeholder] - placeholder text for the empty option\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// Global button registry\n// ---------------------------------------------------------------------------\n\n/**\n * Global registry for custom buttons registered via AutumnNote.registerButton()\n * or via a plugin's `buttons` array. Toolbar resolves string names from here.\n * @type {Map<string, object>}\n */\nexport const _buttonRegistry = new Map();\n\n/**\n * Registers a button definition in the global registry so it can be referenced\n * by string name in toolbar configuration: `toolbar: [['myBtn', boldBtn]]`.\n * @param {object} btnDef - Any ToolbarItemDef-compatible object with a `name` string.\n */\nexport function registerButton(btnDef) {\n if (!btnDef || typeof btnDef.name !== 'string') {\n console.warn('[AutumnNote] registerButton: btnDef must have a string `name` property.');\n return;\n }\n if (_buttonRegistry.has(btnDef.name)) {\n console.warn(`[AutumnNote] registerButton: overwriting existing button \"${btnDef.name}\".`);\n }\n _buttonRegistry.set(btnDef.name, btnDef);\n}\n\n/**\n * Looks up a button definition by name from the global registry.\n * Returns undefined when not found.\n * @param {string} name\n * @returns {object|undefined}\n */\nexport function getButton(name) {\n return _buttonRegistry.get(name);\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 = globalThis.getSelection();\n if (!sel?.rangeCount) return false;\n let sc = sel.getRangeAt(0).startContainer;\n if (sc.nodeType === 3) sc = sc.parentElement;\n return !!(/** @type {Element} */ (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 = globalThis.getSelection();\n if (sel?.rangeCount) {\n let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);\n if (el?.nodeType === 3) el = el.parentElement;\n while (el?.nodeType === 1 && !/** @type {HTMLElement} */ (el).style.fontSize) el = el.parentElement;\n const size = /** @type {HTMLElement} */ (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?.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 = globalThis.getSelection();\n if (!sel?.rangeCount) return '';\n const BLOCKS = new Set(['P','DIV','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE','PRE','TD','TH']);\n let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);\n if (el?.nodeType === 3) el = el.parentElement;\n while (el && !BLOCKS.has(/** @type {Element} */ (el).tagName)) el = el.parentElement;\n if (!el) return '';\n return /** @type {HTMLElement} */ (el).style.lineHeight || getComputedStyle(/** @type {Element} */ (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// ---------------------------------------------------------------------------\n// Buttons namespace — all pre-built button definitions in a single object.\n// Exposed as AutumnNote.buttons so UMD / CJS consumers can access them\n// without named imports: AutumnNote.buttons.boldBtn, etc.\n// ---------------------------------------------------------------------------\n\nexport const buttons = {\n boldBtn,\n italicBtn,\n underlineBtn,\n strikeBtn,\n superscriptBtn,\n subscriptBtn,\n alignLeftBtn,\n alignCenterBtn,\n alignRightBtn,\n alignJustifyBtn,\n ulBtn,\n olBtn,\n indentBtn,\n outdentBtn,\n undoBtn,\n redoBtn,\n hrBtn,\n linkBtn,\n imageBtn,\n videoBtn,\n emojiBtn,\n iconBtn,\n tableBtn,\n fontSizeBtn,\n removeFormatBtn,\n directionBtn,\n fontFamilyBtn,\n paragraphStyleBtn,\n lineHeightBtn,\n codeviewBtn,\n fullscreenBtn,\n shortcutsBtn,\n findBtn,\n findReplaceBtn,\n inlineCodeBtn,\n checklistBtn,\n printBtn,\n foreColorBtn,\n backColorBtn,\n defaultToolbar,\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} [useBootstrap] - Use Bootstrap button classes on toolbar buttons\n * @property {string} [toolbarButtonClass] - CSS classes for Bootstrap toolbar buttons\n * @property {boolean} [useFontAwesome] - Use Font Awesome icons (default: true)\n * @property {string} [fontAwesomeClass] - Font Awesome prefix class, e.g. 'fas' or 'fa-solid'\n * @property {boolean} [fontAwesomeAutoInject] - Let the icon dialog inject Font Awesome CSS from a CDN when the host page has none (default: true)\n * @property {string} [fontAwesomeCDN] - Stylesheet URL used by that injection (defaults to cdnjs FA 6 Free)\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 {number} [historyLimit] - Maximum undo/redo history steps\n * @property {number} [historyMaxBytes] - Maximum combined size (chars) of all stacked undo/redo snapshots\n * @property {string} [defaultFontFamily] - Default font family applied to the editable area on init\n * @property {string} [defaultFontSize] - Default font size applied to the editable area on init (e.g. '14px')\n * @property {string[]} [fontFamilies] - Font families shown in the font-family toolbar dropdown\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} [onInit] - Callback after the editor has initialised\n * @property {Function} [onImageUpload] - Custom upload handler: (files) => void\n * @property {Function} [onImageError] - Callback when an image upload error occurs\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} [autoSaveDelay] - Debounce delay for auto-save writes in milliseconds\n * @property {object|null} [autoSaveAdapter] - Optional async persistence adapter with save/load/remove methods\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} [onPasteError] - Callback fired when pasted or dropped content cannot be processed\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 * @property {boolean} [autoSaveRestore] - Show a restore banner when a previously auto-saved draft exists\n * @property {number} [autoSaveRestoreTimeout] - Maximum age in days for a draft to be offered for restore (0 = no expiry)\n * @property {Function} [onAutoSaveRestore] - Callback fired after the user chooses to restore a draft\n * @property {boolean} [markdownShortcuts] - Convert markdown syntax typed inline to HTML\n * @property {boolean} [bubbleToolbar] - Show a mini floating toolbar above text selections\n * @property {string[]} [bubbleToolbarItems] - Button names for the bubble toolbar\n * @property {object|null} [mention] - @mention configuration (onSearch, minChars, ...)\n * @property {boolean} [slashMenu] - Show a \"/\" command palette for quick block insertion (default true)\n * @property {string} [lang] - Display language or partial locale object override\n */\n\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 // The icon dialog needs FA glyphs to render its grid. When the host page ships\n // no Font Awesome of its own, it pulls the stylesheet from a CDN. Set to false\n // on pages with a strict CSP, an offline deployment, or a no-third-party-request\n // policy — the dialog still works, it just renders without glyphs unless the\n // page provides FA itself.\n fontAwesomeAutoInject: true,\n fontAwesomeCDN: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css',\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 // Max combined size (chars) of all stacked undo/redo snapshots. Guards\n // against documents with many large embedded images holding dozens of\n // full-size copies in memory despite historyLimit.\n historyMaxBytes: 10 * 1024 * 1024,\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 autoSaveDelay: 400,\n autoSaveAdapter: null,\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 for rejected/failed paste and drop payloads: function({ message, size?, maxBytes? })\n onPasteError: 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', 'de', 'es', 'ko'.\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 // \"/\" command palette for quick block insertion (headings, lists, table, image, ...).\n // Triggers only when \"/\" is the first character typed on an otherwise-empty line.\n slashMenu: true,\n // Additional slash-menu commands supplied by applications/plugins.\n slashCommands: [],\n\n // Optional import/export adapters keyed by format name.\n documentAdapters: {},\n // Optional collaboration bridge notified with local HTML changes.\n collaborationAdapter: null,\n\n // Optional image processor (for example a Web Worker bridge). Receives a\n // File and returns a data URL; Clipboard's canvas pipeline remains fallback.\n imageProcessor: null,\n // Add stable data-an-block-id attributes to top-level document blocks.\n blockIds: false,\n\n // Maximum paste size in bytes (default 5 MB). Pastes larger than this are silently dropped.\n maxPasteSize: 5 * 1024 * 1024,\n // Minimum image dimension in px during resize (width and height). Prevents images from being\n // resized below this value.\n minImageSize: 20,\n\n // Bubble toolbar: show a mini floating toolbar above text selections.\n bubbleToolbar: false,\n bubbleToolbarItems: ['bold', 'italic', 'underline', 'link', 'foreColor', 'hiliteColor', '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 wholeWord: 'Whole Word',\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 noResults: 'No results',\n useRegex: 'Use Regular Expression',\n close: '\\u00d7',\n },\n\n autoSaveRestore: {\n found: 'Draft found. Restore?',\n foundAt: 'Draft from {date}. Restore?',\n restore: 'Restore',\n discard: 'Discard',\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 lineNumbers: 'Toggle Line Numbers',\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 tableBorderColor: 'Table Border Color',\n deleteTable: 'Delete Table',\n cellAlignLeft: 'Align Left',\n cellAlignCenter: 'Align Center',\n cellAlignRight: 'Align Right',\n cellAlignJustify: 'Align Justify',\n toggleHeaderRow: 'Toggle Header Row',\n cellBackground: 'Cell Background',\n noShading: 'No Shading',\n noBorderColor: 'No Border Color',\n columnWidthPx: 'Column Width (px)',\n rowHeightPx: 'Row Height (px)',\n tableBorderWidthPx: 'Table Border Width (px)',\n cancelBtn: 'Cancel',\n applyBtn: 'Apply',\n sortAsc: 'Sort Ascending',\n sortDesc: 'Sort Descending',\n exportCSV: 'Export as CSV',\n cellPadding: 'Cell Padding',\n cellPaddingPx: 'Cell Padding (px)',\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 slashMenu: {\n noResults: 'No matching commands',\n heading1: 'Heading 1',\n heading2: 'Heading 2',\n heading3: 'Heading 3',\n bulletList: 'Bullet List',\n numberedList: 'Numbered List',\n checklist: 'Checklist',\n blockquote: 'Blockquote',\n codeBlock: 'Code Block',\n horizontalRule: 'Horizontal Rule',\n table: 'Table',\n image: 'Image',\n },\n};\n","/**\n * i18n/index.js — Locale registry and resolver for autumn-note-ce.\n *\n * Only English ships in the ESM bundle. Bundling all eight locales cost every\n * consumer ~15 KB gzip even when they only ever rendered English, so the other\n * locales are opt-in via subpath imports:\n *\n * import AutumnNote from 'autumnnote';\n * import { vi } from 'autumnnote/i18n/vi';\n *\n * AutumnNote.registerLocale('vi', vi);\n * AutumnNote.create('#editor', { lang: 'vi' });\n *\n * The UMD/CDN build cannot tree-shake, so it pre-registers every locale and\n * `lang: 'vi'` keeps working there with no extra imports.\n *\n * Usage:\n * lang: 'en' → built-in English (always available)\n * lang: '<code>' → a locale previously passed to registerLocale()\n * lang: { ... } → custom locale object, deep-merged over English\n */\n\nimport { mergeDeep } from '../core/func.js';\nimport { en } from './en.js';\n\n/**\n * Locales available to `lang: '<code>'`. Starts with English only; other codes\n * are added through {@link registerLocale}.\n * @type {Record<string, Partial<AsnLocale>>}\n */\nexport const locales = { en };\n\n/**\n * Registers a locale so it can be selected by code.\n *\n * @param {string} code - Language code, e.g. 'vi'.\n * @param {Partial<AsnLocale>} locale - Locale object; missing keys fall back to English.\n * @returns {void}\n */\nexport function registerLocale(code, locale) {\n if (typeof code !== 'string' || !code) {\n throw new TypeError('[AutumnNote] registerLocale: code must be a non-empty string.');\n }\n if (!locale || typeof locale !== 'object') {\n throw new TypeError(`[AutumnNote] registerLocale: locale for \"${code}\" must be an object.`);\n }\n locales[code] = locale;\n}\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 if (!partial) {\n // Unregistered code → English, but say why: silently rendering English\n // after asking for another language is confusing to debug.\n console.warn(\n `[AutumnNote] Locale \"${lang}\" is not registered, falling back to English. ` +\n `Import it first: import { ${lang} } from 'autumnnote/i18n/${lang}'; ` +\n `AutumnNote.registerLocale('${lang}', ${lang});`,\n );\n return en;\n }\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/**\n * Tags that are unconditionally removed from editor content.\n *\n * Beyond the obvious script hosts this covers two SVG/MathML-specific classes:\n *\n * - SMIL animation (`animate`, `set`, `animateTransform`, `animateMotion`)\n * can rewrite an attribute *after* sanitisation finishes, so\n * `<svg><a><animate attributeName=\"href\" values=\"javascript:…\">` survives an\n * attribute-level filter untouched and still navigates on click. The editor\n * only ever emits static `<svg>` icons, so animation is pure attack surface.\n *\n * - `mglyph` / `malignmark` / `annotation-xml` are HTML integration points\n * inside the MathML namespace. They make the parser switch namespaces\n * mid-tree, which is what lets a crafted fragment re-parse into different\n * markup than it serialised from (mXSS). The rest of MathML is left alone so\n * pasted formulae survive.\n */\nconst PROHIBITED_TAGS = [\n 'script', 'style', 'iframe', 'object', 'embed', 'form', 'base', 'template',\n 'link', 'meta', 'noscript', 'portal', 'frame', 'frameset', 'applet',\n 'animate', 'set', 'animatetransform', 'animatemotion',\n 'mglyph', 'malignmark', 'annotation-xml',\n];\n\n/** Tags whose element wrapper is stripped but content (child nodes) is preserved. */\nconst UNWRAP_TAGS = new Set(['button']);\n\n/** Attributes whose values must be sanitised as URLs. */\nconst URL_ATTRS = ['href', 'src', 'action', 'formaction', 'xlink:href', 'poster', 'background', 'srcset'];\n\n/**\n * URL attributes that address media rather than navigation, so they are\n * validated against SAFE_MEDIA_PROTOCOLS regardless of which element carries\n * them (unlike `src`, whose meaning depends on the owning tag).\n */\nconst MEDIA_URL_ATTRS = new Set(['poster', 'background', 'srcset']);\n\n/**\n * Attributes removed outright: the editor never emits them and their only\n * effect is an outbound request the author did not ask for. `ping` fires a\n * POST beacon to arbitrary hosts when a link is clicked.\n */\nconst BEACON_ATTRS = new Set(['ping']);\n\n/** Inline style properties the editor's own toolbar/table features persist on saved content. */\nconst ALLOWED_STYLE_PROPS = new Set([\n 'color', 'background-color', 'font-size', 'line-height',\n 'text-align', 'vertical-align',\n 'width', 'min-width', 'height', 'min-height',\n 'border-width', 'border-style', 'border-color', 'padding',\n]);\n\n/**\n * Value patterns that are never safe regardless of property.\n * `image-set()` and `src()` are covered alongside `url()` — all three fetch an\n * external resource, so allowing them would let pasted content phone home.\n */\nconst DANGEROUS_STYLE_VALUE_RE = /url\\s*\\(|image-set\\s*\\(|src\\s*\\(|expression\\s*\\(|@import|javascript:|vbscript:|behavior\\s*:|-moz-binding/i;\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\nconst SAFE_LINK_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'tel:']);\nconst SAFE_MEDIA_PROTOCOLS = new Set(['http:', 'https:', 'blob:']);\nconst SAFE_RASTER_DATA_RE = /^data:image\\/(?:png|jpe?g|gif|webp|avif|bmp);base64,[a-z0-9+/=\\s]+$/i;\nconst URL_BASE = 'https://autumnnote.invalid/';\n\n/**\n * Produce a sanitized HTML string with dangerous elements and attributes removed.\n *\n * Removes disallowed tags and wrappers, strips event-handler attributes, rejects\n * `javascript:`/`vbscript:` URLs and most `data:` URIs, restricts iframe `src`\n * to trusted hosts when enabled, and permits only checklist checkboxes as inputs.\n *\n * @param {string} html - HTML fragment to sanitize.\n * @param {Object} [options]\n * @param {boolean} [options.allowIframes=false] - If true, `iframe` elements are not removed but their `src` is restricted to trusted hosts and `srcdoc` is removed.\n * @returns {string} The sanitized HTML fragment.\n */\nexport function sanitiseHTML(html, { allowIframes = false } = {}) {\n const doc = new DOMParser().parseFromString(`<body>${html || ''}</body>`, 'text/html');\n\n // Single querySelectorAll pass — collect all elements once to avoid\n // repeated full-tree traversals for each category of check.\n const allElements = Array.from(doc.querySelectorAll('*'));\n\n // Build the prohibited tag set for fast O(1) lookup\n const prohibited = new Set(\n allowIframes ? PROHIBITED_TAGS.filter((t) => t !== 'iframe') : PROHIBITED_TAGS,\n );\n\n for (const el of allElements) {\n const tag = el.tagName.toLowerCase();\n\n // Unwrap elements whose wrapper is unsafe but whose content should be kept\n if (UNWRAP_TAGS.has(tag)) {\n el.replaceWith(...el.childNodes);\n continue;\n }\n\n // Remove outright dangerous elements\n if (prohibited.has(tag)) {\n el.remove();\n continue;\n }\n\n // Invalid embeds are removed rather than retained as empty iframes.\n if (tag === 'iframe') {\n const src = el.getAttribute('src');\n if (!src || !isTrustedIframeSrc(src)) {\n el.remove();\n continue;\n }\n }\n\n // Strip dangerous attributes\n for (const attr of Array.from(el.attributes)) {\n // Remove all event handlers (onclick, onload, onerror, …)\n if (attr.name.startsWith('on')) {\n el.removeAttribute(attr.name);\n continue;\n }\n // Filter the style attribute down to an allowlisted set of safe\n // properties (see ALLOWED_STYLE_PROPS) — not a blanket strip, since\n // the editor's own toolbar/table features persist inline styles\n // (text color/highlight, font size, line height, table alignment/\n // sizing/borders) that must survive sanitisation.\n if (attr.name === 'style') {\n const cleaned = sanitiseStyleValue(attr.value);\n if (cleaned) el.setAttribute('style', cleaned);\n else el.removeAttribute('style');\n continue;\n }\n // Drop tracking-beacon attributes outright\n if (BEACON_ATTRS.has(attr.name)) {\n el.removeAttribute(attr.name);\n continue;\n }\n // Sanitise URL attributes\n if (URL_ATTRS.includes(attr.name)) {\n const val = attr.value.trim();\n const isMediaSource = MEDIA_URL_ATTRS.has(attr.name) ||\n (attr.name === 'src' && ['IMG', 'VIDEO', 'AUDIO', 'SOURCE'].includes(el.tagName));\n const allowData = el.tagName === 'IMG';\n const safe = attr.name === 'srcset'\n ? isSafeSrcset(val, { allowData })\n : isSafeUrl(val, { media: isMediaSource, allowData });\n if (!safe) {\n el.removeAttribute(attr.name);\n continue;\n }\n }\n // Strip iframe HTML-injection vectors; limit src to trusted hosts\n if (el.tagName === 'IFRAME') {\n if (attr.name === 'srcdoc') {\n el.removeAttribute(attr.name);\n continue;\n }\n if (attr.name === 'src' && !isTrustedIframeSrc(attr.value)) {\n el.removeAttribute(attr.name);\n }\n }\n }\n\n if (tag === 'a' && el.getAttribute('target') === '_blank') {\n el.setAttribute('rel', 'noopener noreferrer');\n }\n\n // Allow only input[type=\"checkbox\"] inside ul.an-checklist li\n if (tag === 'input') {\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 for (const attr of Array.from(el.attributes)) {\n if (!['type', 'checked', 'contenteditable'].includes(attr.name)) {\n el.removeAttribute(attr.name);\n }\n }\n }\n }\n }\n\n return doc.body.innerHTML;\n}\n\n/**\n * Filters a style attribute value down to an allowlisted set of CSS\n * properties (ALLOWED_STYLE_PROPS), dropping any declaration whose value\n * contains a dangerous construct — url(), expression(), an \"import\" rule,\n * javascript:/vbscript:, IE behavior/-moz-binding — regardless of property.\n * @param {string} value\n * @returns {string} The filtered declaration list, or '' if nothing survives.\n */\nfunction sanitiseStyleValue(value) {\n const kept = [];\n for (const decl of (value || '').split(';')) {\n const idx = decl.indexOf(':');\n if (idx === -1) continue;\n const prop = decl.slice(0, idx).trim().toLowerCase();\n const val = decl.slice(idx + 1).trim();\n if (!prop || !val) continue;\n if (!ALLOWED_STYLE_PROPS.has(prop)) continue;\n if (DANGEROUS_STYLE_VALUE_RE.test(val)) continue;\n kept.push(`${prop}: ${val}`);\n }\n return kept.join('; ');\n}\n\n/**\n * Validates every candidate URL in a `srcset` attribute.\n *\n * Per the HTML srcset grammar a candidate URL is a run of non-whitespace\n * characters — commas may appear *inside* it, which is why `data:` URLs work\n * there — optionally followed by a width (`300w`) or density (`2x`) descriptor.\n * Splitting on whitespace and skipping descriptor tokens therefore yields the\n * URL set. Anything unparseable makes the whole attribute fail, since a\n * partially-trusted candidate list is not something we can express.\n *\n * @param {string} value\n * @param {{ allowData?: boolean }} [options]\n * @returns {boolean}\n */\nfunction isSafeSrcset(value, { allowData = false } = {}) {\n const tokens = (value || '').trim().split(/\\s+/).filter(Boolean);\n for (const token of tokens) {\n if (/^[\\d.]+[xw],?$/i.test(token)) continue; // width/density descriptor\n const url = token.replace(/,+$/, ''); // trailing comma = candidate separator\n if (!url) continue;\n if (!isSafeUrl(url, { media: true, allowData })) return false;\n }\n return true;\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, media?: boolean }} [opts]\n * @returns {string|null} The original URL if safe, null if rejected.\n */\nexport function sanitiseUrl(url, { allowData = false, media = allowData } = {}) {\n const trimmed = (url || '').trim();\n if (!trimmed && url == null) return null;\n return isSafeUrl(trimmed, { media, allowData }) ? url : null;\n}\n\n/**\n * Validate a URL using the browser URL parser so ASCII whitespace/control\n * characters cannot disguise a dangerous protocol (for example java\\nscript:).\n * @param {string} value\n * @param {{media?: boolean, allowData?: boolean}} [options]\n * @returns {boolean}\n */\nfunction isSafeUrl(value, { media = false, allowData = false } = {}) {\n const trimmed = (value || '').trim();\n if (!trimmed) return true;\n if (allowData && SAFE_RASTER_DATA_RE.test(trimmed)) return true;\n\n try {\n const parsed = new URL(trimmed, URL_BASE);\n const protocols = media ? SAFE_MEDIA_PROTOCOLS : SAFE_LINK_PROTOCOLS;\n return protocols.has(parsed.protocol);\n } catch {\n return false;\n }\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 (_) { void _; }\n }\n if (!initialContent) {\n initialContent = targetEl.tagName === 'TEXTAREA'\n ? ((/** @type {HTMLTextAreaElement} */ (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?.[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 theme — also add to body so floating elements (dialogs, tooltips,\n // popovers) appended to document.body inherit the CSS rules.\n if (options.theme === 'dark') {\n container.classList.add('an-theme-dark');\n document.body.classList.add('an-theme-dark');\n } else if (options.theme === 'auto') {\n container.classList.add('an-theme-auto');\n document.body.classList.add('an-theme-auto');\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.after(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 * @param {number} [maxBytes=10485760] - maximum combined size (chars) of all\n * stacked snapshots (html + tokenized image data). Oldest states are\n * evicted first when exceeded, even if `limit` hasn't been reached —\n * documents with many large embedded images can otherwise hold dozens of\n * full-size copies in memory despite the step-count limit.\n */\n constructor(editable, limit = 100, maxBytes = 10 * 1024 * 1024) {\n this.editable = editable;\n this._limit = limit;\n this._maxBytes = maxBytes;\n this._bytes = 0;\n /** @type {Array<{html: string, images?: Record<string,string>, sel: {start: number, end: number}|null}>} */\n this.stack = [];\n this.stackOffset = -1;\n this._savePoint();\n }\n\n /**\n * Approximate in-memory size (chars) of one stacked snapshot: the tokenized\n * HTML string plus every image data URL it references.\n * @param {{html: string, images?: Record<string,string>}} entry\n * @returns {number}\n */\n _entrySize(entry) {\n let size = entry.html.length;\n if (entry.images) {\n for (const key in entry.images) size += entry.images[key].length;\n }\n return size;\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 = globalThis.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 += /** @type {Text} */ (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 = /** @type {Text} */ (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 ? /** @type {Text} */ (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 = globalThis.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } catch (_) {\n void _; // detached node — fall back to placing cursor at start of editable\n try {\n const fb = document.createRange();\n fb.setStart(this.editable, 0);\n fb.collapse(true);\n const s = globalThis.getSelection();\n if (s) { s.removeAllRanges(); s.addRange(fb); }\n } catch (_2) { void _2; /* fully give up */ }\n }\n }\n\n _savePoint() {\n // Trim future history if we're mid-stack\n if (this.stackOffset < this.stack.length - 1) {\n for (const entry of this.stack.slice(this.stackOffset + 1)) {\n this._bytes -= this._entrySize(entry);\n }\n this.stack = this.stack.slice(0, this.stackOffset + 1);\n }\n const raw = this._serialize();\n const { html, images } = this._tokenizeImages(raw);\n const entry = { html, images, sel: this._serializeSelection() };\n this.stack.push(entry);\n this._bytes += this._entrySize(entry);\n\n // Evict oldest states first, whichever budget (step count or byte size)\n // is exceeded — always keep at least the just-pushed current state.\n while (this.stack.length > 1 && (this.stack.length > this._limit || this._bytes > this._maxBytes)) {\n this._bytes -= this._entrySize(this.stack.shift());\n }\n // The newly-pushed current state is always the final entry. Recompute the\n // offset from the resulting stack instead of incrementing conditionally:\n // a single oversized snapshot may evict several older entries at once.\n this.stackOffset = this.stack.length - 1;\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 // Fast-path: skip regex entirely when there are no data URIs (common case)\n if (!html.includes('data:')) return { html, images: /** @type {Record<string,string>} */ ({}) };\n const images = /** @type {Record<string,string>} */ ({});\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?.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._bytes = 0;\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 /** @returns {number} */\n getUndoCount() {\n return Math.max(0, this.stackOffset);\n }\n\n /** @returns {number} */\n getRedoCount() {\n return Math.max(0, this.stack.length - 1 - this.stackOffset);\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';\n\n// ---------------------------------------------------------------------------\n// Table creation\n// ---------------------------------------------------------------------------\n\n/**\n * Build an HTML table with the given number of columns and rows, optionally including a header row.\n * @param {number} cols - Number of columns in each row.\n * @param {number} rows - Total number of rows to create (including header when `headerRow` is true).\n * @param {{ headerRow?: boolean }} [opts] - Options: `headerRow` creates a `<thead>` when true.\n * @returns {HTMLTableElement} The constructed `<table>` element with a `<tbody>` and optional `<thead>`; each cell contains a `<br>` placeholder.\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', {}, [document.createElement('br')]);\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', {}, [document.createElement('br')]);\n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n return /** @type {HTMLTableElement} */ (table);\n}\n\n/**\n * Insert a table at the current selection and place the caret into its first cell.\n * @param {number} cols - Number of columns for the new table.\n * @param {number} rows - Number of rows for the new table.\n * @param {{ headerRow?: boolean }} [opts] - Options for table creation.\n */\nexport function insertTable(cols, rows, opts = {}) {\n if (cols <= 0 || rows <= 0) return;\n const table = createTable(cols, rows, opts);\n\n const sel = globalThis.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n try {\n range.deleteContents();\n } catch (_) {\n return;\n }\n\n // Walk up to find the nearest block-level ancestor to insert after\n const BLOCK = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI', 'PRE']);\n let anchor = /** @type {Element|null} */ (range.startContainer);\n if (anchor?.nodeType === 3) anchor = anchor.parentElement;\n while (anchor && !BLOCK.has(anchor.tagName?.toUpperCase()) && anchor.parentElement) {\n anchor = anchor.parentElement;\n }\n\n if (anchor && BLOCK.has(anchor.tagName?.toUpperCase()) && anchor.parentNode) {\n anchor.after(table);\n // Ensure there's a paragraph after the table for cursor landing\n if (!table.nextElementSibling) {\n const p = document.createElement('p');\n p.appendChild(document.createElement('br'));\n table.after(p);\n }\n // Remove the anchor block if it was empty (common case: cursor in blank paragraph)\n if (!anchor.textContent.trim() && !anchor.querySelector('img, video, table')) {\n anchor.remove();\n }\n } else {\n try {\n range.insertNode(table);\n } catch (_) {\n return;\n }\n }\n\n // Place cursor in the first cell\n const firstCell = table.querySelector('td, th');\n if (firstCell) {\n const nr = document.createRange();\n nr.setStart(firstCell, 0);\n nr.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nr);\n }\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?.nodeName === 'I' && _FA_PATTERN.test(n.className || ''));\nconst isZwsAnchor = (n) => !!(n?.nodeType === Node.TEXT_NODE && (n.textContent === '\\u200B' || n.textContent === ''));\n\n/**\n * Extracts the content from `startContainer:startOffset` to the end of `li`.\n * Returns an empty fragment if the range is invalid (e.g. detached node).\n * @param {Range} nativeRange\n * @param {Element} li\n * @returns {DocumentFragment}\n */\nfunction extractAfterContent(nativeRange, li) {\n try {\n const r = document.createRange();\n r.setStart(nativeRange.startContainer, nativeRange.startOffset);\n r.setEnd(li, li.childNodes.length);\n return r.extractContents();\n } catch (_) {\n void _;\n return document.createDocumentFragment();\n }\n}\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 = globalThis.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 = globalThis.getSelection();\n if (sel?.rangeCount > 0) {\n const r = sel.getRangeAt(0);\n if (r.collapsed && r.startContainer.nodeType === Node.TEXT_NODE) {\n const textNode = /** @type {ChildNode} */ (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 /** @type {ChildNode} */ (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 = /** @type {ChildNode} */ (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?.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 = globalThis.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?.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?.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?.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?.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 using configured tabSize\n if (para?.nodeName.toUpperCase() === 'PRE') {\n if (event.shiftKey) return false;\n event.preventDefault();\n execCommand('insertText', ' '.repeat(options.tabSize || 4));\n return true;\n }\n\n // Default: insert &nbsp; * 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 = /** @type {Element|null} */ (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?.nodeName === 'I' && /\\bfa-/.test(el.className || '')) {\n const nr = document.createRange();\n nr.setStartAfter(el);\n nr.collapse(true);\n const selI = globalThis.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?.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 = globalThis.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?.closest('.an-checklist li');\n if (checkLi) {\n event.preventDefault();\n const ul = checkLi.closest('.an-checklist');\n const sel = globalThis.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 if (sel.rangeCount === 0 || !checkLi.isConnected) return true;\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 afterFrag = extractAfterContent(nativeRange, checkLi);\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?.nodeType !== Node.TEXT_NODE) {\n cursorNode = document.createTextNode('\\u200B');\n newLi.appendChild(cursorNode);\n }\n checkLi.after(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 // Enter in a pre/code block: insert a literal newline instead of a new block\n if (para?.nodeName.toUpperCase() === 'PRE') {\n event.preventDefault();\n execCommand('insertText', '\\n');\n return true;\n }\n\n // Pressing Enter at the end of a blockquote should exit it\n if (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\n/**\n * Convert a DOM node subtree into Markdown.\n *\n * Recursively produces a Markdown string representing the given DOM node and its descendants,\n * handling common HTML constructs such as paragraphs, headings, lists (with nested indentation),\n * blockquotes, fenced and inline code, links, images, tables, horizontal rules, and basic inline emphasis.\n *\n * @param {Node} node - The DOM node to convert.\n * @param {number} [depth=0] - Current nesting depth used to indent nested list items.\n * @returns {string} The Markdown representation of the node subtree.\n */\n/**\n * Direct child elements matching a tag name. Used instead of the CSS\n * `:scope > tag` combinator, which this project's jsdom version resolves\n * incorrectly (matches descendants at any depth, not just direct children).\n * @param {Element} el\n * @param {string} tagName\n * @returns {Element[]}\n */\nfunction _directChildren(el, tagName) {\n return Array.from(el.children).filter((c) => c.tagName === tagName.toUpperCase());\n}\n\nfunction _domToMd(node, depth = 0) {\n if (node.nodeType === 3) {\n return node.textContent.replace(/\\s+/g, ' ');\n }\n if (node.nodeType !== 1) return '';\n\n const el = /** @type {Element} */ (node);\n const tag = el.nodeName.toLowerCase();\n const inner = () => Array.from(el.childNodes).map(n => _domToMd(n, depth)).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 'u': return `<u>${inner()}</u>`;\n case 'span': {\n // Markdown has no native underline/color/size syntax; pass through as\n // raw inline HTML for the specific styles the editor's own toolbar\n // creates (foreColor/backColor/fontSize) — other noise spans (e.g. from\n // pasted content) are unwrapped to plain text as before.\n const style = el.getAttribute('style') || '';\n if (/\\b(color|background-color|font-size)\\s*:/.test(style)) {\n return `<span style=\"${_escAttr(style)}\">${inner()}</span>`;\n }\n return inner();\n }\n case 'code': {\n // Inside <pre> we emit raw text; outside we wrap in backticks\n if (el.closest('pre')) return inner();\n return `\\`${inner()}\\``;\n }\n case 'pre': {\n const codeEl = el.querySelector('code');\n const langMatch = /language-(\\S+)/.exec(codeEl?.className || '');\n const lang = langMatch ? langMatch[1] : '';\n const content = (codeEl || el).textContent || '';\n return `\\n\\n\\`\\`\\`${lang}\\n${content}\\n\\`\\`\\`\\n\\n`;\n }\n case 'blockquote': {\n const rawLines = inner().trim().split('\\n');\n // Collapse consecutive blank lines (from adjacent <p> blocks) into one.\n const lines = rawLines.filter((l, idx) => l.trim() !== '' || (rawLines[idx - 1] ?? '').trim() !== '');\n return `\\n\\n${lines.map((l) => (l.trim() === '' ? '>' : `> ${l}`)).join('\\n')}\\n\\n`;\n }\n case 'a': {\n const href = el.getAttribute('href') || '';\n return `[${inner()}](${href})`;\n }\n case 'img': {\n const src = el.getAttribute('src') || '';\n const alt = el.getAttribute('alt') || '';\n return `![${alt}](${src})`;\n }\n case 'ul': {\n const items = _directChildren(el, 'li');\n if (!items.length) return inner();\n const indent = ' '.repeat(depth);\n const isChecklist = el.classList.contains('an-checklist');\n const lines = items.map((li) => {\n const cb = /** @type {HTMLInputElement | undefined} */ (\n _directChildren(li, 'input').find((c) => c.getAttribute('type') === 'checkbox')\n );\n let prefix = '- ';\n if (isChecklist || cb) {\n const checked = cb ? cb.checked : false;\n prefix = checked ? '- [x] ' : '- [ ] ';\n }\n return `${indent}${prefix}${_domToMd(li, depth + 1).trim()}`;\n }).join('\\n');\n return depth === 0 ? `\\n\\n${lines}\\n\\n` : `\\n${lines}`;\n }\n case 'ol': {\n const items = _directChildren(el, 'li');\n if (!items.length) return inner();\n const indent = ' '.repeat(depth);\n const lines = items.map((li, i) => `${indent}${i + 1}. ${_domToMd(li, depth + 1).trim()}`).join('\\n');\n return depth === 0 ? `\\n\\n${lines}\\n\\n` : `\\n${lines}`;\n }\n case 'li': return inner();\n case 'hr': return '\\n\\n---\\n\\n';\n case 'table': {\n const allRows = Array.from(el.querySelectorAll('tr'));\n if (!allRows.length) return inner();\n const theadEl = _directChildren(el, 'thead')[0];\n const firstRowIsHeader = !!theadEl || (\n allRows[0].children.length > 0 &&\n Array.from(allRows[0].children).every((c) => c.tagName === 'TH')\n );\n const cellTexts = allRows.map((tr) =>\n Array.from(tr.querySelectorAll('th, td')).map((c) => c.textContent.trim().replaceAll('|', String.raw`\\|`)),\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 const bodyStart = firstRowIsHeader ? 1 : 0;\n const headerCells = firstRowIsHeader ? padRow(cellTexts[0]) : new Array(cols).fill('');\n let md = '\\n\\n';\n md += `| ${headerCells.join(' | ')} |\\n`;\n md += `| ${new Array(cols).fill('---').join(' | ')} |\\n`;\n for (let r = bodyStart; 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 * Detects whether a string likely contains Markdown syntax.\n *\n * Checks for common Markdown constructs such as ATX headings, unordered or\n * ordered list items, blockquotes, fenced code blocks, and bold emphasis.\n * @param {string} text - Input text to inspect for Markdown patterns.\n * @returns {boolean} `true` if any Markdown-like pattern is present, `false` otherwise.\n */\nexport function isMarkdown(text) {\n return /^#{1,6} [^\\s]|^[ \\t]*[-*+] [^\\s]|^[ \\t]*\\d+\\. [^\\s]|^> ?[^\\s]|^```|^\\*{2}[^*\\n]+\\*{2}/m.test(text)\n || /^.+\\n=+\\s*$/m.test(text)\n || /^.+\\n-{2,}\\s*$/m.test(text)\n || /^---\\s*\\n(?:[\\s\\S]*?\\n)?(?:---|\\.\\.\\.)\\s*(?:\\n|$)/.test(text)\n || /^\\|.+\\|[ \\t]*\\n\\|[ \\t:|-]+\\|/m.test(text);\n}\n\n// Blockquote line: optional up-to-3 leading spaces, '>', optional single space, rest of line.\nconst BQ_RE = /^ {0,3}>( ?)(.*)$/;\n// Horizontal rule: 3+ of the same character (-, * or _), optionally space-separated.\nconst HR_RE = /^ {0,3}([-*_])( *\\1){2,}\\s*$/;\n// Hard-break marker — placed between paragraph lines that end in a\n// CommonMark hard-break (trailing 2+ spaces or a trailing backslash),\n// restored to <br> after _inline() runs. Distinct from _inline()'s own MARK.\nconst HARD_BREAK = String.fromCharCode(1);\n\n/**\n * Converts a Markdown string to an HTML string.\n * @param {string} text\n * @returns {string}\n */\nexport function markdownToHTML(text) {\n let lines = text.replaceAll('\\r\\n', '\\n').replaceAll('\\r', '\\n').split('\\n');\n lines = _stripFrontmatter(lines);\n const refs = _extractReferenceDefinitions(lines);\n lines = refs.clean;\n _linkDefs = refs.linkDefs;\n _footnoteIds = refs.footnoteIds;\n return _parseBlocks(lines);\n}\n\n/**\n * Parses a line array into block-level HTML. Called recursively for content\n * nested inside a blockquote so nested quotes and block content (lists,\n * headings, etc.) inside `>` are parsed the same as top-level content.\n * @param {string[]} lines\n * @returns {string}\n */\nfunction _parseBlocks(lines) {\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 = /^```(\\S*)$/.exec(line);\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 // ---- Setext headings (Title\\n=== or Title\\n---) -------------------------\n if (line.trim() && !HR_RE.test(line) && !/^#{1,6} /.test(line) && i + 1 < lines.length) {\n if (/^=+\\s*$/.test(lines[i + 1])) {\n out.push(`<h1>${_inline(line.trim())}</h1>`);\n i += 2;\n continue;\n }\n if (/^-{2,}\\s*$/.test(lines[i + 1])) {\n out.push(`<h2>${_inline(line.trim())}</h2>`);\n i += 2;\n continue;\n }\n }\n\n // ---- Horizontal rule --- / *** / ___ / - - - / * * * ----------------------\n if (HR_RE.test(line)) {\n out.push('<hr>');\n i++;\n continue;\n }\n\n // ---- ATX Headings # – ###### -------------------------------------------\n const hMatch = /^(#{1,6})\\s+(.+)$/.exec(line);\n if (hMatch) {\n const level = hMatch[1].length;\n // Strip an optional closing sequence of #'s (e.g. \"## Heading ##\"),\n // only when preceded by whitespace — \"Heading#\" (no space) is untouched.\n const content = hMatch[2].replace(/(?:^|\\s)#+\\s*$/, '');\n out.push(`<h${level}>${_inline(content)}</h${level}>`);\n i++;\n continue;\n }\n\n // ---- Blockquote > text --------------------------------------------------\n if (BQ_RE.test(line)) {\n const bqLines = [];\n while (i < lines.length && BQ_RE.test(lines[i])) {\n bqLines.push(BQ_RE.exec(lines[i])[2]);\n i++;\n }\n out.push(`<blockquote>${_parseBlocks(bqLines)}</blockquote>`);\n continue;\n }\n\n // ---- Checklist or Unordered list - / * / + item ----------------------\n if (/^[-*+] /.test(line)) {\n const { html: listHtml, endIdx } = _parseListBlock(lines, i);\n out.push(listHtml); i = endIdx; continue;\n }\n\n // ---- Ordered list 1. item ----------------------------------------------\n if (/^\\d+\\. /.test(line)) {\n const { html: listHtml, endIdx } = _parseListBlock(lines, i);\n out.push(listHtml); i = endIdx; 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 const alignments = _parseTableRow(lines[i + 1]).map((c) => {\n if (c.startsWith(':') && c.endsWith(':')) return 'center';\n if (c.endsWith(':')) return 'right';\n if (c.startsWith(':')) return 'left';\n return null;\n });\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 _cell = (tag, content, align) => {\n const s = align ? ` style=\"text-align:${align}\"` : '';\n return `<${tag}${s}>${_inline(content)}</${tag}>`;\n };\n const thCells = headerCells.map((c, idx) => _cell('th', c, alignments[idx])).join('');\n const thead = `<thead><tr>${thCells}</tr></thead>`;\n const renderRow = (row) => `<tr>${row.map((c, idx) => _cell('td', c, alignments[idx])).join('')}</tr>`;\n const tbody = bodyRows.length ? `<tbody>${bodyRows.map(renderRow).join('')}</tbody>` : '';\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+\\. |```)/.test(lines[i]) &&\n !BQ_RE.test(lines[i]) &&\n !HR_RE.test(lines[i]) &&\n !/^\\|.+\\|/.test(lines[i]) &&\n !(i + 1 < lines.length && /^=+\\s*$/.test(lines[i + 1])) &&\n !(i + 1 < lines.length && /^-{2,}\\s*$/.test(lines[i + 1]))\n ) {\n paraLines.push(lines[i]);\n i++;\n }\n if (paraLines.length) {\n out.push(`<p>${_inline(_joinParagraphLines(paraLines)).replaceAll(HARD_BREAK, '<br>')}</p>`);\n }\n }\n\n return out.join('');\n}\n\n// ---------------------------------------------------------------------------\n// Inline formatting\n// ---------------------------------------------------------------------------\n\n/** Reference-link and footnote definitions collected per markdownToHTML() call. */\nlet _linkDefs = new Map();\nlet _footnoteIds = new Set();\n\n/**\n * Strips a leading YAML frontmatter block (--- ... --- or --- ... ...) from\n * the line array, only when it is the very first line and the enclosed body\n * looks like YAML (key: value / list items / indented continuations) — this\n * disambiguates real frontmatter from a horizontal rule followed by prose.\n * @param {string[]} lines\n * @returns {string[]}\n */\nfunction _stripFrontmatter(lines) {\n if ((lines[0] || '').trim() !== '---') return lines;\n let closeIdx = -1;\n for (let j = 1; j < lines.length; j++) {\n const t = lines[j].trim();\n if (t === '---' || t === '...') { closeIdx = j; break; }\n }\n if (closeIdx === -1) return lines;\n\n const body = lines.slice(1, closeIdx);\n const looksLikeYAML = body.every((l) =>\n l.trim() === '' ||\n /^[ \\t]*[\\w$.-]+\\s*:(\\s|$)/.test(l) ||\n /^[ \\t]*-\\s+\\S/.test(l) ||\n /^[ \\t]+\\S/.test(l));\n if (!looksLikeYAML) return lines;\n\n let start = closeIdx + 1;\n if (lines[start] !== undefined && lines[start].trim() === '') start++;\n return lines.slice(start);\n}\n\n/**\n * Extracts GFM reference-link definitions (`[ref]: url \"title\"`) and footnote\n * definitions (`[^id]: text`) from the line array, skipping fenced code\n * regions. Returns the definition-free line array plus lookup maps.\n * @param {string[]} lines\n * @returns {{ clean: string[], linkDefs: Map<string, {href: string, title?: string}>, footnoteIds: Set<string> }}\n */\nfunction _extractReferenceDefinitions(lines) {\n const linkDefs = new Map();\n const footnoteIds = new Set();\n const clean = [];\n let inFence = false;\n const linkDefRe = /^\\[([^\\]]+)\\]:\\s*(\\S+)(?:\\s+\"([^\"]*)\")?\\s*$/;\n const footnoteDefRe = /^\\[\\^([^\\]]+)\\]:\\s*(.+)$/;\n\n for (const line of lines) {\n if (/^```/.test(line)) { inFence = !inFence; clean.push(line); continue; }\n if (!inFence) {\n const fm = footnoteDefRe.exec(line);\n if (fm) { footnoteIds.add(fm[1]); continue; }\n const lm = linkDefRe.exec(line);\n if (lm) { linkDefs.set(lm[1].trim().toLowerCase(), { href: lm[2], title: lm[3] }); continue; }\n }\n clean.push(line);\n }\n return { clean, linkDefs, footnoteIds };\n}\n\n/**\n * Joins a paragraph's source lines into one string, converting CommonMark\n * hard-break markers (a trailing backslash, or 2+ trailing spaces) on all\n * but the last line into a HARD_BREAK placeholder instead of a plain space.\n * @param {string[]} paraLines\n * @returns {string}\n */\nfunction _joinParagraphLines(paraLines) {\n let joined = '';\n for (let idx = 0; idx < paraLines.length; idx++) {\n const isLast = idx === paraLines.length - 1;\n const ln = paraLines[idx];\n if (!isLast && /\\\\$/.test(ln)) { joined += ln.replace(/\\\\$/, '') + HARD_BREAK; continue; }\n if (!isLast && / {2,}$/.test(ln)) { joined += ln.replace(/ {2,}$/, '') + HARD_BREAK; continue; }\n joined += ln + (isLast ? '' : ' ');\n }\n return joined;\n}\n\n/**\n * Splits a GFM table row string into trimmed cell strings, treating an\n * escaped pipe (`\\|`) as a literal character rather than a cell separator.\n * '| a | b | c |' → ['a', 'b', 'c']; '| a\\|b | c |' → ['a|b', 'c']\n * @param {string} row\n * @returns {string[]}\n */\nfunction _parseTableRow(row) {\n const trimmed = row.replace(/^\\|/, '').replace(/\\|$/, '');\n const cells = [];\n let cur = '';\n for (let i = 0; i < trimmed.length; i++) {\n if (trimmed[i] === '\\\\' && trimmed[i + 1] === '|') { cur += '|'; i++; continue; }\n if (trimmed[i] === '|') { cells.push(cur); cur = ''; continue; }\n cur += trimmed[i];\n }\n cells.push(cur);\n return cells.map((c) => c.trim());\n}\n\nfunction _parseListBlock(lines, startIdx) {\n const baseIndent = (lines[startIdx].match(/^(\\s*)/)[1]).length;\n const isOL = /^\\s*\\d+\\. /.test(lines[startIdx]);\n const items = [];\n let firstIsCB = null;\n let loose = false;\n let pendingBlank = false;\n let i = startIdx;\n\n while (i < lines.length) {\n const line = lines[i];\n\n if (line.trim() === '') {\n // A blank line only ends the list if what follows isn't a continuation\n // of it (another item at the same marker/indent, or indented text\n // belonging to the current item) — otherwise it marks a \"loose\" list.\n const next = lines[i + 1];\n const nextIndent = next !== undefined ? (next.match(/^(\\s*)/)[1]).length : -1;\n const nextIsSameItem = next !== undefined &&\n /^\\s*(?:[-*+]|\\d+\\.) /.test(next) &&\n (/^\\s*\\d+\\. /.test(next) === isOL) &&\n nextIndent === baseIndent;\n const nextIsContinuation = next !== undefined && next.trim() !== '' && nextIndent > baseIndent;\n if (!items.length || (!nextIsSameItem && !nextIsContinuation)) break;\n loose = true;\n pendingBlank = true;\n i++;\n continue;\n }\n\n const indent = (line.match(/^(\\s*)/)[1]).length;\n if (indent < baseIndent) break;\n\n if (indent === baseIndent) {\n if (!/^\\s*(?:[-*+]|\\d+\\.) /.test(line)) break;\n if (/^\\s*\\d+\\. /.test(line) !== isOL) break;\n const raw = isOL ? line.replace(/^\\s*\\d+\\. /, '') : line.replace(/^\\s*[-*+] /, '');\n // Checklists are intentionally UL-only: sanitise.js's checkbox guard,\n // the injected checklist CSS, and every checklist-toggle command are\n // all hardcoded to `ul.an-checklist` with no `ol` equivalent, so an\n // ordered-list checkbox would be stripped by the sanitiser and get no\n // styling even if parsed here — \"1. [ ] item\" intentionally stays plain.\n const isCB = !isOL && /^\\[[ xX]\\]\\s+/.test(raw);\n if (firstIsCB === null) firstIsCB = isCB;\n if (isCB !== firstIsCB) break;\n const checked = isCB && raw[1].toLowerCase() === 'x';\n const text = isCB ? raw.replace(/^\\[[ xX]\\]\\s+/, '') : raw;\n items.push({ paras: [text], isCB, checked, sub: '' });\n pendingBlank = false;\n i++;\n } else {\n if (!items.length) { i++; continue; }\n if (/^\\s*(?:[-*+]|\\d+\\.) /.test(line)) {\n const nested = _parseListBlock(lines, i);\n items[items.length - 1].sub += nested.html;\n i = nested.endIdx;\n pendingBlank = false;\n } else if (pendingBlank) {\n items[items.length - 1].paras.push(line.trim());\n pendingBlank = false;\n i++;\n } else {\n const paras = items[items.length - 1].paras;\n paras[paras.length - 1] += ' ' + line.trim();\n i++;\n }\n }\n }\n\n const hasCB = !isOL && (firstIsCB === true);\n const startMatch = isOL ? /^\\s*(\\d+)\\. /.exec(lines[startIdx]) : null;\n const startNum = startMatch ? Number.parseInt(startMatch[1], 10) : 1;\n const open = isOL\n ? (startNum !== 1 ? `<ol start=\"${startNum}\">` : '<ol>')\n : (hasCB ? '<ul class=\"an-checklist\">' : '<ul>');\n const close = isOL ? '</ol>' : '</ul>';\n const liHTML = items.map(({ paras, isCB, checked, sub }) => {\n const cbHTML = isCB\n ? `<input type=\"checkbox\" contenteditable=\"false\"${checked ? ' checked' : ''}>`\n : '';\n const body = loose\n ? paras.map((p, idx) => `<p>${idx === 0 ? cbHTML : ''}${_inline(p)}</p>`).join('')\n : `${cbHTML}${_inline(paras[0])}`;\n return `<li>${body}${sub}</li>`;\n }).join('');\n return { html: `${open}${liHTML}${close}`, endIdx: i };\n}\n\n// Backslash-escapable inline punctuation (CommonMark-ish, narrowed to the\n// syntax characters this converter actually uses).\nconst ESCAPABLE_RE = /\\\\([*_`#[\\]()>\\\\~|])/g;\n// Placeholder marker for escaped literals — a NUL character can't appear in\n// real markdown text, so it's safe as a delimiter. Built at runtime (not\n// written as a literal escape) to avoid embedding a raw NUL byte in this file.\nconst MARK = String.fromCharCode(0);\n\n/**\n * Step 0 of _inline(): replaces backslash-escaped punctuation with inert\n * placeholders so later syntax regexes can't match them.\n * @param {string} text\n * @returns {{ text: string, literals: string[] }}\n */\nfunction _extractBackslashEscapes(text) {\n const literals = [];\n const replaced = text.replace(ESCAPABLE_RE, (_, ch) => {\n literals.push(ch);\n return `${MARK}${literals.length - 1}${MARK}`;\n });\n return { text: replaced, literals };\n}\n\n/**\n * Restores placeholders from _extractBackslashEscapes(), HTML-escaping each\n * literal since it's inserted directly into the output.\n * @param {string} text\n * @param {string[]} literals\n * @returns {string}\n */\nfunction _restoreBackslashEscapes(text, literals) {\n return text.replace(new RegExp(`${MARK}(\\\\d+)${MARK}`, 'g'), (_, idx) => _esc(literals[Number(idx)]));\n}\n\n/**\n * Resolves images, inline links, GFM reference-style links (explicit,\n * shortcut, and bare/implicit forms), and footnote markers. Must run on text\n * already passed through _esc() — see _inline()'s Step 1 comment.\n * @param {string} text\n * @returns {string}\n */\nfunction _resolveLinksAndFootnotes(text) {\n text = text.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, (_, alt, src) =>\n `<img src=\"${_escAttrQuotes(src)}\" alt=\"${_escAttrQuotes(alt)}\" class=\"an-image\">`);\n text = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, label, href) =>\n `<a href=\"${_escAttrQuotes(href)}\">${label}</a>`);\n text = text.replace(/\\[([^\\]]+)\\]\\[([^\\]]*)\\]/g, (m, label, ref) => {\n const def = _linkDefs.get(_unescAmpLtGt(ref || label).trim().toLowerCase());\n if (!def) return m;\n const titleAttr = def.title ? ` title=\"${_escAttr(def.title)}\"` : '';\n return `<a href=\"${_escAttr(def.href)}\"${titleAttr}>${label}</a>`;\n });\n text = text.replace(/\\[([^\\]]+)\\]/g, (m, label) => {\n const def = _linkDefs.get(_unescAmpLtGt(label).trim().toLowerCase());\n if (!def) return m;\n const titleAttr = def.title ? ` title=\"${_escAttr(def.title)}\"` : '';\n return `<a href=\"${_escAttr(def.href)}\"${titleAttr}>${label}</a>`;\n });\n text = text.replace(/\\[\\^([^\\]]+)\\]/g, (m, id) => (_footnoteIds.has(_unescAmpLtGt(id)) ? `<sup>[${id}]</sup>` : m));\n return text;\n}\n\n/**\n * Converts angle-bracket (`<https://...>`) and bare (`https://...`)\n * autolinks. Runs after _resolveLinksAndFootnotes() so an already-linked URL\n * isn't reprocessed, and on already-_esc()'d text (see _inline()).\n * @param {string} text\n * @returns {string}\n */\nfunction _applyAutolinks(text) {\n text = text.replace(/&lt;(https?:\\/\\/[^\\s&]+?)&gt;/g, (_, url) => `<a href=\"${_escAttrQuotes(url)}\">${url}</a>`);\n text = text.replace(/(^|[\\s(])(https?:\\/\\/[^\\s()]+)/g, (m, pre, rawUrl) => {\n const trail = /[.,;:!?)]+$/.exec(rawUrl);\n const url = trail ? rawUrl.slice(0, -trail[0].length) : rawUrl;\n if (!url) return m;\n const suffix = trail ? trail[0] : '';\n return `${pre}<a href=\"${_escAttrQuotes(url)}\">${url}</a>${suffix}`;\n });\n return text;\n}\n\n/**\n * Applies bold/italic/bold-italic (asterisk and underscore forms — underscore\n * requires a non-word-character boundary per CommonMark), strikethrough, and\n * inline code.\n * @param {string} text\n * @returns {string}\n */\nfunction _applyEmphasisAndCode(text) {\n text = text.replace(/\\*{3}([^*\\n]+?)\\*{3}/g, (_, c) => `<strong><em>${c}</em></strong>`);\n text = text.replace(/(?<!\\w)_{3}([^_\\n]+?)_{3}(?!\\w)/g, (_, c) => `<strong><em>${c}</em></strong>`);\n text = text.replace(/\\*{2}([^*\\n]+?)\\*{2}/g, (_, c) => `<strong>${c}</strong>`);\n text = text.replace(/(?<!\\w)_{2}([^_\\n]+?)_{2}(?!\\w)/g, (_, c) => `<strong>${c}</strong>`);\n text = text.replace(/\\*([^*\\n]+?)\\*/g, (_, c) => `<em>${c}</em>`);\n text = text.replace(/(?<!\\w)_([^_\\n]+?)_(?!\\w)/g, (_, c) => `<em>${c}</em>`);\n text = text.replace(/~~([^~\\n]+?)~~/g, (_, c) => `<del>${c}</del>`);\n // Double-backtick code spans first (tolerates a single literal ` inside),\n // then single-backtick spans.\n text = text.replace(/``([\\s\\S]*?)``/g, (_, c) => `<code>${c}</code>`);\n text = text.replace(/`([^`]+)`/g, (_, c) => `<code>${c}</code>`);\n return text;\n}\n\nfunction _inline(text) {\n // Step 0: backslash escapes (\\* \\_ \\` \\# \\[ \\] \\( \\) \\> \\\\ \\~ \\|) — replaced\n // with inert placeholders before any syntax regex below can match them, so\n // e.g. \\*not bold\\* never gets treated as emphasis. Restored at the end.\n const { text: withoutEscapes, literals } = _extractBackslashEscapes(text);\n\n // Step 1: escape raw &/</> in the plain-text parts of the string exactly\n // once, up front — none of these are markdown-syntax characters used below,\n // so this doesn't interfere with matching. Capture-group content in the\n // steps below is therefore ALREADY escaped and must NOT be re-escaped;\n // attribute values captured from `text` only need quotes escaped\n // (_escAttrQuotes), since & < > are already entities. Values that come from\n // _linkDefs (sourced from the raw, unescaped line array) still need the\n // full _escAttr/_esc treatment.\n let result = _esc(withoutEscapes);\n\n result = _resolveLinksAndFootnotes(result);\n result = _applyAutolinks(result);\n result = _applyEmphasisAndCode(result);\n\n return _restoreBackslashEscapes(result, literals);\n}\n\nfunction _esc(v) {\n return String(v)\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\n}\n\nfunction _escAttr(v) {\n return String(v)\n .replaceAll('&', '&amp;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\n}\n\n/** Escapes only quote characters — for attribute values already run through _esc(). */\nfunction _escAttrQuotes(v) {\n return String(v).replaceAll('\"', '&quot;').replaceAll(\"'\", '&#39;');\n}\n\n/** Reverses _esc()'s &amp;/&lt;/&gt; substitutions, for matching against un-escaped _linkDefs/_footnoteIds keys. */\nfunction _unescAmpLtGt(v) {\n return String(v).replaceAll('&lt;', '<').replaceAll('&gt;', '>').replaceAll('&amp;', '&');\n}\n","/**\n * detectLang.js — Heuristic programming-language detection for code snippets.\n *\n * Returns a Prism.js language identifier or null when no language can be\n * determined with reasonable confidence.\n *\n * Detection order (conflicts in parentheses):\n * TypeScript → Rust → PHP → Java → Kotlin → Swift → Go\n * → JavaScript → HTML → CSS → JSON → SQL → Python → Ruby\n * → Bash → C++ → C# → C → XML\n *\n * @param {string} code\n * @returns {string|null}\n */\nexport function detectLang(code) {\n if (!code?.trim()) return null;\n const s = code.trim();\n\n // ── TypeScript ─────────────────────────────────────────────────────────────\n // Must be first — TS is a JS superset; its markers are specific.\n if (/(:\\s*(string|number|boolean|void|never|any|unknown)\\b|interface\\s+\\w+\\s*\\{|type\\s+\\w+\\s*[=<(]|<\\w+>\\s*[;,)]|readonly\\s+\\w|enum\\s+\\w+\\s*\\{|\\?\\s*:\\s*\\w|as\\s+\\w+\\s*[;,)\\]])/.test(s)) return 'typescript';\n\n // ── Rust ────────────────────────────────────────────────────────────────────\n // Before JavaScript — both have `let`. `!` macros and `pub fn` are unique.\n if (/\\bprintln!\\s*\\(|\\bprint!\\s*\\(|\\bfn\\s+\\w+\\s*(<[^>]*>)?\\s*\\(|\\blet\\s+mut\\s|\\bpub\\s+fn\\s|\\buse\\s+std::|\\bimpl\\s+\\w+|\\bOption<|\\bResult<\\w+/.test(s)) return 'rust';\n\n // ── PHP ─────────────────────────────────────────────────────────────────────\n // Before Bash — both have `echo`. `<?php` and `$var` are unique to PHP.\n if (/(<\\?php\\b|<\\?=|\\becho\\s+.*\\$\\w|\\$this->|\\$\\w+\\s*=\\s*\\w|\\bforeach\\s*\\(\\s*\\$|Illuminate\\\\)/.test(s)) return 'php';\n\n // ── Java ────────────────────────────────────────────────────────────────────\n // Before Kotlin — `System.out.println()` would otherwise match Kotlin's\n // `println\\s*\\(` pattern.\n if (/\\bpublic\\s+(class|static|void|int|String)\\s+\\w|System\\.out\\.(print|println)\\s*\\(|@(Override|Autowired|Component|Service|Controller)\\b|import\\s+java\\.(util|io|lang|net)\\.|throws\\s+\\w+Exception/.test(s)) return 'java';\n\n // ── Kotlin ──────────────────────────────────────────────────────────────────\n // Kotlin uses `val` (immutable) unlike Swift/JS which use `let`.\n // `fun`, `data class`, `companion object`, `println()` are Kotlin-specific.\n if (/\\bfun\\s+\\w+\\s*\\(|\\bdata\\s+class\\s+\\w+|\\bcompanion\\s+object\\b|\\bval\\s+\\w+\\s*:\\s*\\w|\\bprintln\\s*\\(/.test(s)) return 'kotlin';\n\n // ── Swift ───────────────────────────────────────────────────────────────────\n // Swift uses `let` for constants (Kotlin uses `val`). `guard let`, `protocol`,\n // `extension`, `func ... -> ReturnType`, and `let x: UppercaseType` are signals.\n if (/\\bguard\\s+(let|var)\\b|\\bprotocol\\s+\\w+\\s*\\{|\\bextension\\s+\\w+|\\bfunc\\s+\\w+[^(]*\\([^)]*\\)\\s*->\\s*\\w|\\blet\\s+\\w+\\s*:\\s*[A-Z]\\w*|\\bSwiftUI\\b/.test(s)) return 'swift';\n\n // ── Go ──────────────────────────────────────────────────────────────────────\n // `package`, `:=` short assignment, `fmt.Print*`, `chan`, `goroutine`.\n if (/\\bpackage\\s+\\w+\\b|\\bfmt\\.(Print|Println|Sprintf|Errorf|Fprintf)\\s*\\(|:=\\s*\\w|\\bgoroutine\\b|\\bchan\\s+\\w|\\bgo\\s+func\\b/.test(s)) return 'go';\n\n // ── JavaScript ──────────────────────────────────────────────────────────────\n // Before HTML to handle JSX (`<div/>` would otherwise trigger HTML).\n // `var\\s+\\w+\\s*=` (not just `var\\s+\\w`) to avoid matching Swift `var x: Int`.\n if (/\\b(const\\s+\\w|let\\s+\\w+\\s*=|var\\s+\\w+\\s*=|function\\s+\\w|\\=>\\s*[{(]|import\\s+.*\\bfrom\\b\\s*['\"]|require\\s*\\(|console\\.(log|error|warn|info)|document\\.\\w|window\\.\\w|async\\s+function|\\bPromise\\b|React\\.|useState\\s*\\(|\\.then\\s*\\()/.test(s)) return 'javascript';\n\n // ── HTML ────────────────────────────────────────────────────────────────────\n if (/^<!DOCTYPE html/i.test(s) || /<(html|head|body|div|section|article|nav|p|a|img|ul|ol|li|table|form|input|button|script|style)\\b[^>]*>/i.test(s)) return 'html';\n\n // ── SCSS ─────────────────────────────────────────────────────────────────────\n // Before CSS — SCSS is a superset. Unique markers: `//` line comments,\n // `&` nesting, `$variable`, `@mixin/@include/@extend`, `#{interpolation}`.\n if (/(^|\\n)\\s*(\\/\\/\\s+\\S|&[:.[\\w]|\\$\\w+\\s*:|@(mixin|include|extend|each|if|for|use|forward)\\b|#\\{)/.test(s) && /[\\w#.*&[\\]:(),>+~ -]+\\s*\\{/.test(s)) return 'scss';\n\n // ── CSS ──────────────────────────────────────────────────────────────────────\n if (/(^|\\n)\\s*[\\w#.*:[\\]&, +-]+\\s*\\{[^}]*[\\w-]+\\s*:[^{}:;]+[;}\\n]/m.test(s) && !/<\\w|function\\s|def\\s|:\\s*(string|number)/.test(s)) return 'css';\n\n // ── JSON ────────────────────────────────────────────────────────────────────\n if (/^\\s*[{[]/.test(s) && /\"\\w[\\w\\s-]*\"\\s*:/.test(s) && !/\\bfunction\\b|\\bdef\\b/.test(s)) return 'json';\n\n // ── SQL ─────────────────────────────────────────────────────────────────────\n if (/(^|\\n)\\s*(SELECT\\s|INSERT\\s+INTO|UPDATE\\s+\\w|DELETE\\s+FROM|CREATE\\s+(TABLE|DATABASE|INDEX|VIEW)|DROP\\s+(TABLE|DATABASE)|ALTER\\s+TABLE|WITH\\s+\\w+\\s+AS\\s*\\()/im.test(s)) return 'sql';\n\n // ── Python ──────────────────────────────────────────────────────────────────\n // `def` requires trailing `:` (Python rule); `class` checked at line start.\n if (/\\bdef\\s+\\w+\\s*\\([^)]*\\)\\s*:|(^|\\n)\\s*class\\s+\\w+.*:\\s*$|(^|\\n)\\s*import\\s+\\w|(^|\\n)\\s*from\\s+\\w+\\s+import\\s+|\\bprint\\s*\\(|if\\s+__name__\\s*==\\s*['\"]__main__['\"]/m.test(s)) return 'python';\n\n // ── Ruby ────────────────────────────────────────────────────────────────────\n // `.each do |x|`, `attr_*`, `puts` with value, multi-line `def...end`.\n if (/\\bputs\\s+\\S|\\battr_(accessor|reader|writer)\\s|\\.each\\s+do\\s*\\|\\w+\\s*\\||\\bdo\\s*\\|\\w+\\s*\\|.*\\bend\\b|\\bdef\\s+\\w+[^:]*\\n[\\s\\S]*?\\bend\\b/.test(s)) return 'ruby';\n\n // ── Bash / Shell ─────────────────────────────────────────────────────────────\n if (/^#!.*\\/(ba|z|da|fi|k)?sh\\b/m.test(s) || /\\b(echo\\s+[\"']|grep\\s+|awk\\s+|sed\\s+['\"\\\\/-]|chmod\\s+|sudo\\s+|apt(-get)?\\s+install|brew\\s+install|npm\\s+(install|run|start|build)|pip\\s+(install|3\\s)|docker\\s+(run|build|compose)|kubectl\\s+|git\\s+(clone|add|commit|push|pull|checkout))\\b/.test(s)) return 'bash';\n\n // ── C++ ─────────────────────────────────────────────────────────────────────\n // Before C and C# — `cout<<`, `using namespace std`, `std::`, `template<>`.\n if (/\\bcout\\s*<<|\\bcin\\s*>>|using\\s+namespace\\s+std\\b|std::\\w|\\btemplate\\s*<\\w|\\b#include\\s*<(iostream|vector|map|set|algorithm|string|memory)>/.test(s)) return 'cpp';\n\n // ── C# ──────────────────────────────────────────────────────────────────────\n // After C++ to avoid matching C++'s `using namespace std`.\n if (/\\busing\\s+System\\b|Console\\.(Write|WriteLine)\\s*\\(|\\bget;\\s*set;|\\basync\\s+Task[<\\s]|IEnumerable<|\\bLINQ\\b|\\.Select\\s*\\(|\\.Where\\s*\\(/.test(s)) return 'csharp';\n\n // ── C ───────────────────────────────────────────────────────────────────────\n if (/\\b#include\\s*<(stdio|stdlib|string|math|time|ctype)\\.h>|\\bprintf\\s*\\(|\\bscanf\\s*\\(|int\\s+main\\s*\\(\\s*(void|int\\s+argc)|\\bmalloc\\s*\\(|\\bfree\\s*\\(/.test(s) && !/namespace|cout|cin|std::/.test(s)) return 'c';\n\n // ── XML ─────────────────────────────────────────────────────────────────────\n if (/^<\\?xml\\s/i.test(s) || /xmlns:|<\\/[\\w:]+>/.test(s)) return 'xml';\n\n return null;\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';\nimport { detectLang } from '../core/detectLang.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(\n editable,\n this.options.historyLimit || 100,\n this.options.historyMaxBytes || 10 * 1024 * 1024,\n );\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 = globalThis.getSelection();\n if (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 = globalThis.getSelection();\n if (!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 scEl = /** @type {Element} */ (sc);\n const li = scEl.matches('.an-checklist li') ? scEl : 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?.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 = /** @type {Element} */ (e.target);\n if (target && (target.nodeName === 'IFRAME' ||\n 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 = globalThis.getSelection();\n if (!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) {\n const el = /** @type {Element} */ (node);\n if (el.closest('sup')) _compositionSupSub = 'superscript';\n else if (el.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 = globalThis.getSelection();\n if (!sel?.rangeCount) return;\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n const el = /** @type {Element} */ (node);\n const inContext = tag === 'superscript' ? el?.closest('sup') : el?.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.replaceAll('\\n', '').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 // Ensure the editable always ends with a paragraph so the user can click\n // and type after block elements that trap the cursor (pre, table, etc.).\n this._ensureTrailingParagraph();\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.remove();\n }\n });\n }\n\n /**\n * Ensures the editable always ends with a plain paragraph so the cursor can\n * be placed after block elements that do not naturally allow it\n * (pre, blockquote, table, figure, ul, ol, hr).\n * Without this, clicking below the last such element does nothing.\n */\n _ensureTrailingParagraph() {\n const editable = this.context.layoutInfo.editable;\n if (!editable) return;\n const last = editable.lastElementChild;\n if (!last) return;\n const TRAPPING = new Set(['PRE', 'BLOCKQUOTE', 'TABLE', 'FIGURE', 'UL', 'OL', 'HR']);\n if (TRAPPING.has(last.nodeName)) {\n const p = document.createElement('p');\n p.innerHTML = '<br>';\n editable.appendChild(p);\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.replaceAll('\\u200B', '');\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 .replaceAll('\\u00a0', '');\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 this._flushPendingSnapshot();\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 this._flushPendingSnapshot();\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 /** Records a debounced change before an immediate undo/redo command. */\n _flushPendingSnapshot() {\n if (this._snapshotTimer === null) return;\n clearTimeout(this._snapshotTimer);\n this._snapshotTimer = null;\n this._history?.recordUndo();\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 getUndoCount() {\n return this._history ? this._history.getUndoCount() : 0;\n }\n\n getRedoCount() {\n return this._history ? this._history.getRedoCount() : 0;\n }\n\n getSelectionBookmark() {\n return this._history?._serializeSelection() ?? null;\n }\n\n restoreSelectionBookmark(bookmark) {\n if (!bookmark || !this._history) return false;\n this._history._restoreSelection(bookmark);\n return true;\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', 'pre'\n */\n formatBlock(tagName) {\n Style.formatBlock(tagName);\n\n // Auto-detect the programming language when the user formats a code block.\n // Only runs when converting TO <pre> and the block has no language yet.\n if (tagName === 'pre') {\n const sel = globalThis.getSelection();\n if (sel?.rangeCount > 0) {\n const container = sel.getRangeAt(0).commonAncestorContainer;\n const pre = /** @type {Element|null} */ (\n container.nodeType === 1\n ? /** @type {Element} */ (container).closest('pre')\n : (/** @type {Element|null} */ (container.parentElement))?.closest('pre')\n );\n if (pre && !/** @type {HTMLElement} */ (pre).dataset.language) {\n const code = pre.textContent || '';\n const lang = detectLang(code);\n if (lang) {\n this.context.invoke('codeTooltip.applyLanguage', pre, lang);\n return; // applyLanguage already calls afterCommand internally\n }\n }\n }\n }\n\n this.afterCommand();\n }\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 = globalThis.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 Style.execCommand('createLink', safeUrl);\n if (openInNewTab) {\n const link = this._getClosestAnchor();\n if (link) {\n /** @type {Element} */ (link).setAttribute('target', '_blank');\n /** @type {Element} */ (link).setAttribute('rel', 'noopener noreferrer');\n }\n }\n } else {\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 }\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 = globalThis.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 .replaceAll('&', '&amp;')\n .replaceAll('\"', '&quot;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\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';\nimport { getButton } from './Buttons.js';\n\n/** Resolve a toolbar item: string → registry lookup, object → pass-through. */\nconst _resolveBtn = (item) => (typeof item === 'string') ? getButton(item) : item;\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 /** @type {number|null} rAF handle for debounced refresh */\n this._refreshRaf = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n this.el = createElement('div', {\n class: 'an-toolbar',\n role: 'toolbar',\n 'aria-orientation': 'horizontal',\n // Matches the hardcoded English label renderer.js gives the editable.\n 'aria-label': 'Editor toolbar',\n });\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._initRovingFocus();\n this._btnMap = new Map(\n (this.options.toolbar || []).flat()\n .map(_resolveBtn).filter(Boolean).map((b) => [b.name, b]),\n );\n return this;\n }\n\n destroy() {\n if (this._refreshRaf) cancelAnimationFrame(this._refreshRaf);\n this._refreshRaf = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this.el?.parentNode) {\n this.el.remove();\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((item) => {\n const btnDef = _resolveBtn(item);\n if (!btnDef) {\n console.warn(`[AutumnNote] Toolbar: button \"${item}\" not found in registry. Skipped.`);\n return;\n }\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.dataset.row;\n const c = +cell.dataset.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 const rect = btn.getBoundingClientRect();\n\n // Measure popup dimensions while invisible so we can set the correct\n // position before the browser paints (matches the color-picker pattern).\n popup.style.visibility = 'hidden';\n popup.style.display = 'block';\n const pw = popup.offsetWidth;\n const ph = popup.offsetHeight;\n\n let left = rect.left;\n let top = rect.bottom + 4;\n if (left + pw > globalThis.innerWidth - 8) left = Math.max(8, globalThis.innerWidth - pw - 8);\n if (top + ph > globalThis.innerHeight - 8) top = rect.top - ph - 4;\n\n popup.style.left = `${left}px`;\n popup.style.top = `${top}px`;\n popup.style.visibility = '';\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 = /** @type {HTMLElement|null} */ (/** @type {Element} */ (e.target)?.closest('.an-table-cell'));\n if (!cell) return;\n setHighlight(+cell.dataset.row, +cell.dataset.col);\n });\n\n const d3 = on(grid, 'mouseleave', () => setHighlight(0, 0));\n\n const d4 = on(grid, 'click', (e) => {\n const cell = /** @type {HTMLElement|null} */ (/** @type {Element} */ (e.target)?.closest('.an-table-cell'));\n if (!cell) return;\n const rows = +cell.dataset.row;\n const cols = +cell.dataset.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 // Append popup to body so position:fixed is truly viewport-relative,\n // unaffected by any ancestor transform / filter (same pattern as color picker).\n this._disposers.push(d1, d2, d3, d4, d5, () => {\n if (popup.parentNode) popup.remove();\n });\n\n wrap.appendChild(btn);\n document.body.appendChild(popup);\n return /** @type {HTMLDivElement} */ (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 = /** @type {HTMLInputElement} */ (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 = globalThis.getSelection();\n savedRange = sel?.rangeCount ? sel.getRangeAt(0).cloneRange() : null;\n };\n\n const restoreSelection = () => {\n if (!savedRange) return;\n try {\n const sel = globalThis.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(savedRange);\n } catch (_) {\n void _; // range may be stale 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 > globalThis.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 = /** @type {Element} */ (e.target)?.closest('.an-color-swatch');\n if (sw) applyColor(/** @type {HTMLElement} */ (sw).dataset.color);\n });\n\n const d4 = on(colorInput, 'change', (e) => {\n applyColor(/** @type {HTMLInputElement} */ (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(/** @type {Node} */ (e.target)) && !popup.contains(/** @type {Node} */ (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 globalThis.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 () => globalThis.removeEventListener('resize', onScrollResize),\n // Remove popup from body on editor destroy\n () => { if (popup.parentNode) popup.remove(); },\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 /** @type {HTMLDivElement} */ (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 let label;\n if (typeof item !== 'object') {\n label = item;\n } else if (def.name === 'paragraphStyle') {\n label = this.context.locale.toolbar.paragraphItems?.[item.value] || item.label;\n } else {\n label = item.label;\n }\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 = globalThis.getSelection();\n _savedRange = 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 = globalThis.getSelection();\n if (sel) { sel.removeAllRanges(); sel.addRange(_savedRange); }\n } catch (_) { void _; /* 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 /** @type {HTMLSelectElement} */ (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 // A button that reports an active state is a toggle, so its state has to\n // be exposed to assistive tech and not only through the `.active` class.\n ...(typeof btnDef.isActive === 'function' ? { 'aria-pressed': 'false' } : {}),\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 if (_SVG_MAP.has(btnDef.icon)) {\n // FontAwesome absent: use SVG fallback when available\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 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 /** @type {HTMLButtonElement} */ (btn);\n }\n\n // ---------------------------------------------------------------------------\n // Keyboard navigation — WAI-ARIA toolbar pattern\n // ---------------------------------------------------------------------------\n\n /**\n * Every control the toolbar contains, in visual order. Disabled ones are\n * included so their tabindex can be cleared; `_navigable()` filters them out.\n * @returns {HTMLElement[]}\n */\n _controls() {\n if (!this.el) return [];\n return /** @type {HTMLElement[]} */ (Array.from(this.el.querySelectorAll('button, select')));\n }\n\n /** @returns {HTMLElement[]} controls that can actually receive focus */\n _navigable() {\n return this._controls().filter(\n (el) => !(/** @type {HTMLButtonElement} */ (el).disabled),\n );\n }\n\n /**\n * Enforces the roving-tabindex invariant: exactly one control sits in the tab\n * order and the rest are reached with arrow keys. The default toolbar renders\n * 39 controls, so without this a keyboard user pressed Tab 39 times to get\n * past the toolbar and into the editable area.\n *\n * @param {HTMLElement} [focused] - control that should own the tab stop;\n * omitted on refresh, where the user's current position is preserved.\n */\n _syncRovingTabindex(focused) {\n const all = this._controls();\n const navigable = this._navigable();\n if (!navigable.length) return;\n const active = (focused && navigable.includes(focused))\n ? focused\n : navigable.find((el) => el.getAttribute('tabindex') === '0') || navigable[0];\n all.forEach((el) => el.setAttribute('tabindex', el === active ? '0' : '-1'));\n }\n\n /** Wires arrow-key navigation. Called on build and again after rebuild(). */\n _initRovingFocus() {\n if (!this.el) return;\n this._syncRovingTabindex();\n this._disposers.push(\n on(this.el, 'keydown', (e) => this._onToolbarKeydown(/** @type {KeyboardEvent} */ (e))),\n // Clicking or programmatically focusing a control moves the tab stop with\n // it, so Tab always leaves from wherever the user actually is.\n on(this.el, 'focusin', (e) => {\n const el = /** @type {Element} */ (e.target)?.closest?.('button, select');\n if (el) this._syncRovingTabindex(/** @type {HTMLElement} */ (el));\n }),\n );\n }\n\n /**\n * Home/End jump to the ends; Left/Right step between controls and wrap.\n * Up/Down are deliberately left alone so `<select>` controls keep their\n * native value-changing behaviour.\n * @param {KeyboardEvent} event\n */\n _onToolbarKeydown(event) {\n if (!['ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(event.key)) return;\n const controls = this._navigable();\n const current = /** @type {HTMLElement|null} */ (\n /** @type {Element} */ (event.target)?.closest?.('button, select')\n );\n const idx = current ? controls.indexOf(current) : -1;\n if (idx === -1) return;\n\n let next;\n if (event.key === 'Home') {\n next = controls[0];\n } else if (event.key === 'End') {\n next = controls.at(-1);\n } else {\n // In RTL the arrow that points at the next control is the left one.\n const rtl = this.options.direction === 'rtl';\n const forward = (event.key === 'ArrowRight') !== rtl;\n next = controls[(idx + (forward ? 1 : -1) + controls.length) % controls.length];\n }\n if (!next) return;\n event.preventDefault();\n this._syncRovingTabindex(next);\n next.focus();\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) => /** @type {HTMLLinkElement} */ (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 // Debounce via rAF — multiple rapid calls (e.g. afterCommand + button click)\n // collapse into a single update per animation frame.\n if (this._refreshRaf) cancelAnimationFrame(this._refreshRaf);\n this._refreshRaf = requestAnimationFrame(() => {\n this._refreshRaf = null;\n this._doRefresh();\n });\n }\n\n _doRefresh() {\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(/** @type {HTMLElement} */ (btn).dataset.btn);\n if (def && typeof def.isActive === 'function') {\n const active = !!def.isActive(this.context);\n btn.classList.toggle('active', active);\n btn.setAttribute('aria-pressed', String(active));\n }\n if (def && typeof def.isDisabled === 'function') {\n /** @type {HTMLButtonElement} */ (btn).disabled = !!def.isDisabled(this.context);\n }\n });\n\n // A button disabled just now must not be the one holding the tab stop.\n this._syncRovingTabindex();\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(/** @type {HTMLElement} */ (select).dataset.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?.[0]\n || '';\n }\n // Try to match against available options (case-insensitive)\n const sel = /** @type {HTMLSelectElement} */ (select);\n const matched = Array.from(sel.options).find(\n (opt) => opt.value?.toLowerCase() === raw.toLowerCase()\n );\n sel.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 * Tears down and re-renders the toolbar in-place.\n * Call after registering new buttons post-create via context.use(plugin)\n * or AutumnNote.registerButton() to make them appear in the toolbar.\n */\n rebuild() {\n if (this._refreshRaf) { cancelAnimationFrame(this._refreshRaf); this._refreshRaf = null; }\n this._disposers.forEach((d) => d());\n this._disposers = [];\n if (this.el) this.el.innerHTML = '';\n this._faReady = this._detectFontAwesome();\n this._buildButtons();\n // rebuild() cleared the disposers, taking the keydown/focusin listeners\n // with them — re-arm navigation over the new controls.\n this._initRovingFocus();\n this._btnMap = new Map(\n (this.options.toolbar || []).flat()\n .map(_resolveBtn).filter(Boolean).map((b) => [b.name, b]),\n );\n this.refresh();\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';\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', role: 'status', 'aria-live': 'polite', 'aria-atomic': 'true' });\n this._charCountEl = createElement('span', { class: 'an-char-count', 'aria-live': 'polite', 'aria-atomic': 'true' });\n const info = createElement('div', { class: 'an-status-info', 'aria-label': 'Editor statistics' });\n info.appendChild(this._wordCountEl);\n info.appendChild(this._charCountEl);\n this.el.appendChild(info);\n\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 this.el?.remove();\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 + /** @type {HTMLElement} */ (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 // Editor.afterCommand() already invokes 'statusbar.update' on every native\n // 'input' event and after every toolbar/formatting command, so a separate\n // content listener here would just re-run this on the same keystroke.\n update() {\n if (!this._wordCountEl || !this._charCountEl) return;\n const editable = this.context.layoutInfo.editable;\n // textContent is faster than innerText (no layout flush, no CSS visibility check)\n const text = editable.textContent || '';\n const words = _countWords(text);\n const chars = text.replaceAll('\\n', '').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 || '').replaceAll('\\n', '').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?.size) return;\n const imgs = /** @type {Element[]} */ ([]);\n if (node.nodeName === 'IMG') {\n imgs.push(/** @type {Element} */ (node));\n } else if (/** @type {Element} */ (node).querySelectorAll) {\n imgs.push(.../** @type {Element} */ (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*(&nbsp;)?\\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 el.remove();\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 * Normalizes task lists from external sources (GitHub, GitLab, etc.) so they\n * pass the sanitiser's `ul.an-checklist` guard. Runs before sanitiseHTML().\n * @param {string} html\n * @returns {string}\n */\n _normalizeExternalTaskLists(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n for (const cb of doc.querySelectorAll('input[type=\"checkbox\"]')) {\n const li = cb.closest('li');\n const ul = li?.closest('ul');\n if (!li || !ul || ul.classList.contains('an-checklist')) continue;\n ul.classList.add('an-checklist');\n cb.removeAttribute('disabled');\n cb.setAttribute('contenteditable', 'false');\n for (const attr of Array.from(cb.attributes)) {\n if (!['type', 'checked', 'contenteditable'].includes(attr.name)) {\n cb.removeAttribute(attr.name);\n }\n }\n }\n return doc.body.innerHTML;\n }\n\n /**\n * Checks whether an HTML payload has no semantic markup beyond plain\n * wrapper elements (e.g. a bare <div>/<p>). Used to decide whether a\n * markdown-shaped plain-text paste should win over an accompanying HTML\n * payload that isn't actually carrying any real rich-text formatting.\n * @param {string} html\n * @returns {boolean}\n */\n _isTriviallyPlainHtml(html) {\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, 'text/html');\n const SIGNIFICANT = 'a,img,table,ul,ol,li,blockquote,pre,code,h1,h2,h3,h4,h5,h6,strong,b,em,i,u,s,del,strike,hr,br';\n return !doc.body.querySelector(SIGNIFICANT);\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 || /** @type {any} */ (globalThis).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 // Enforce maxPasteSize limit (default 5 MB)\n const maxBytes = (this.options.maxPasteSize ?? 5) * 1024 * 1024;\n if (maxBytes > 0) {\n const text = clipboardData.getData('text/plain') || '';\n const html = clipboardData.getData('text/html') || '';\n const size = Math.max(text.length, html.length);\n if (size > maxBytes) {\n event.preventDefault();\n const message = `Pasted content (${size} bytes) exceeds the ${this.options.maxPasteSize ?? 5} MB paste size limit.`;\n this.context.triggerEvent('pasteError', { size, maxBytes, message });\n console.warn(`[AutumnNote] ${message}`);\n return;\n }\n }\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 — when there's no HTML on the clipboard, or the\n // accompanying HTML has no semantic markup (e.g. some terminal/clipboard\n // tools put both a markdown-shaped text/plain and a trivial <div>-wrapped\n // text/html on the clipboard). Real rich-text sources (Word, Docs, etc.)\n // always have semantic tags after cleaning, so this is unaffected.\n if (this.options.markdownPaste !== false) {\n const hasHtml = clipboardData.types.includes('text/html');\n const html = hasHtml ? clipboardData.getData('text/html') : '';\n const htmlTriviallyPlain = !hasHtml || this._isTriviallyPlainHtml(html);\n const text = clipboardData.getData('text/plain');\n if (text && htmlTriviallyPlain && isMarkdown(text)) {\n event.preventDefault();\n const converted = sanitiseHTML(markdownToHTML(text));\n execCommand('insertHTML', converted);\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 = /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 = this._normalizeExternalTaskLists(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 }\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?.files?.length) return;\n\n const imageFiles = Array.from(dt.files).filter((f) => f.type.startsWith('image/'));\n if (imageFiles.length > 0) {\n event.preventDefault();\n event.stopPropagation();\n // Place the caret at the drop coordinates before inserting\n this._placeCaretAtPoint(event.clientX, event.clientY);\n this._insertImageFiles(imageFiles);\n return;\n }\n\n if (this.options.markdownPaste !== false) {\n const mdFile = Array.from(dt.files).find((f) => /\\.md$/i.test(f.name) || f.type === 'text/markdown');\n if (mdFile) {\n event.preventDefault();\n event.stopPropagation();\n this._placeCaretAtPoint(event.clientX, event.clientY);\n this._insertMarkdownFile(mdFile);\n }\n }\n }\n\n /**\n * Reads a dropped `.md` File and inserts it converted to HTML at the\n * current caret. Skips the isMarkdown() heuristic — an explicit `.md`\n * extension/MIME type is an unambiguous signal, unlike pasted plain text.\n * @param {File} file\n */\n _insertMarkdownFile(file) {\n const maxBytes = (this.options.maxPasteSize ?? 5) * 1024 * 1024;\n if (maxBytes > 0 && file.size > maxBytes) {\n const message = `Dropped file \"${file.name}\" (${file.size} bytes) exceeds the ${this.options.maxPasteSize ?? 5} MB paste size limit.`;\n this.context.triggerEvent('pasteError', { size: file.size, maxBytes, message });\n console.warn(`[AutumnNote] ${message}`);\n return;\n }\n const reader = new FileReader();\n reader.onload = (e) => {\n const html = sanitiseHTML(markdownToHTML(/** @type {string} */ (e.target.result) || ''));\n execCommand('insertHTML', html);\n this.context.invoke('editor.afterCommand');\n };\n reader.onerror = () => {\n const message = `Failed to read dropped markdown file \"${file.name}\".`;\n console.warn(`[AutumnNote] ${message}`);\n this.context.triggerEvent('pasteError', { message });\n };\n reader.readAsText(file);\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 = new Set(['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?.type?.startsWith('image/')) return;\n if (UNSUPPORTED.has(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.compressAndRegister(file).then((blobUrl) => {\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 * Compresses an image File via canvas and registers the result behind a\n * lightweight blob: URL (see `resolveImages`), so callers never have to hold\n * the full base64 string in the DOM. Shared by paste/drop and ImageDialog's\n * file picker so every image-insertion path gets the same compression.\n * @param {File} file\n * @returns {Promise<string>} blob: URL usable as an <img src>\n */\n async compressAndRegister(file) {\n const processor = this.options.imageProcessor;\n const dataUrl = typeof processor === 'function'\n ? await processor(file, { context: this.context })\n : await this._compressImage(file);\n const blob = this._dataUrlToBlob(dataUrl);\n const blobUrl = URL.createObjectURL(blob);\n this._blobRegistry.set(blobUrl, dataUrl);\n return blobUrl;\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?.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 = /:(.*?);/.exec(header)?.[1] ?? 'image/png';\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, reject) => {\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.onerror = () => reject(new Error('FileReader failed'));\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.onerror = () => reject(new Error('FileReader failed'));\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 = globalThis.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 .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#039;');\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.replaceAll('\\u200B', '').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 this._textarea?.remove();\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 = /** @type {HTMLTextAreaElement} */ (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.remove();\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 (stripped.startsWith('</')) 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(/** @type {KeyboardEvent} */ (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","import { createElement, on, trapFocus, makeDraggable } from '../core/dom.js';\nimport { withSavedRange } from '../core/range.js';\n\n/**\n * Shared lifecycle and shell-building logic for all modal dialogs.\n * Subclasses implement _buildDialog() for their specific form fields.\n */\nexport class BaseDialog {\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 /** @type {HTMLElement|null} First focusable input; set by subclass in _buildDialog(). */\n this._firstInput = null;\n this._removeTrap = null;\n }\n\n // ---------------------------------------------------------------------------\n // Abstract — subclasses must override\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLElement} */\n _buildDialog() { throw new Error('_buildDialog() must be implemented by subclass'); }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (shared)\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?.parentNode) {\n this._dialog.remove();\n }\n this._dialog = null;\n }\n\n // ---------------------------------------------------------------------------\n // Shared show helpers\n // ---------------------------------------------------------------------------\n\n /** Saves the current selection range before opening the dialog. */\n _saveRange() {\n withSavedRange((range) => { this._savedRange = range; });\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._firstInput?.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 // Shell builders (used by subclass _buildDialog())\n // ---------------------------------------------------------------------------\n\n /**\n * Builds the overlay + box + header shell common to all dialogs.\n * Also wires up draggable and overlay-click-to-close.\n * @param {string} ariaLabel\n * @param {string} iconHtml Raw SVG string for the dialog icon\n * @param {string} titleText\n * @returns {{ overlay: HTMLElement, box: HTMLElement }}\n */\n _buildDialogShell(ariaLabel, iconHtml, titleText) {\n const overlay = createElement('div', {\n class: 'an-dialog-overlay',\n role: 'dialog',\n 'aria-modal': 'true',\n 'aria-label': ariaLabel,\n });\n const box = createElement('div', { class: 'an-dialog-box' });\n\n const header = createElement('div', { class: 'an-dialog-header' });\n const iconEl = createElement('span', { class: 'an-dialog-icon' });\n iconEl.innerHTML = iconHtml;\n const titleEl = createElement('h3', { class: 'an-dialog-title' });\n titleEl.textContent = titleText;\n header.appendChild(iconEl);\n header.appendChild(titleEl);\n\n box.appendChild(header);\n overlay.appendChild(box);\n makeDraggable(header, box);\n\n const d = on(overlay, 'click', (e) => { if (e.target === overlay) this._close(); });\n this._disposers.push(d);\n\n return { overlay, box };\n }\n\n /**\n * Builds an action button row with a primary insert button and a cancel button.\n * Disposers are registered automatically.\n * @param {string} insertLabel\n * @param {string} cancelLabel\n * @param {() => void} onInsert\n * @returns {HTMLElement}\n */\n _buildButtonRow(insertLabel, cancelLabel, onInsert) {\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 = insertLabel;\n const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });\n cancelBtn.textContent = cancelLabel;\n btnRow.appendChild(insertBtn);\n btnRow.appendChild(cancelBtn);\n\n const d1 = on(insertBtn, 'click', onInsert);\n const d2 = on(cancelBtn, 'click', () => this._close());\n this._disposers.push(d1, d2);\n\n return btnRow;\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 } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" 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\nexport class LinkDialog extends BaseDialog {\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 this._saveRange();\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, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);\n\n // URL field\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.url;\n const urlInput = /** @type {HTMLInputElement} */ (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 this._firstInput = urlInput;\n\n // Text field\n const textLabel = createElement('label', { class: 'an-label' });\n textLabel.textContent = L.displayText;\n const textInput = /** @type {HTMLInputElement} */ (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 = /** @type {HTMLInputElement} */ (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 const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());\n\n box.append(urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);\n\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(textInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(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 = globalThis.getSelection();\n let anchor = null;\n if (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 = /** @type {Element} */ (anchor).getAttribute('href') || '';\n this._textInput.value = anchor.textContent || '';\n this._tabCheckbox.checked = /** @type {Element} */ (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","/**\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 } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" 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\nexport class ImageDialog extends BaseDialog {\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * @param {{ beforeInsert?: () => void }} [hooks]\n */\n show({ beforeInsert } = {}) {\n this._beforeInsert = typeof beforeInsert === 'function' ? beforeInsert : null;\n this._saveRange();\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, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);\n\n // URL field\n const urlLabel = createElement('label', { class: 'an-label' });\n urlLabel.textContent = L.imageUrl;\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 this._firstInput = urlInput;\n\n // Alt text\n const altLabel = createElement('label', { class: 'an-label' });\n altLabel.textContent = L.altText;\n const altInput = /** @type {HTMLInputElement} */ (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(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 = /** @type {HTMLInputElement} */ (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\n if (this.options.allowImageUpload !== false) {\n const fileLabel = createElement('label', { class: 'an-label' });\n fileLabel.textContent = L.uploadLabel;\n const fileInput = /** @type {HTMLInputElement} */ (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 const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());\n box.append(btnRow);\n\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n const d5 = on(altInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d4, d5);\n\n return overlay;\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n _onFileChange() {\n if (this.context._alive === false) return;\n const file = this._fileInput?.files?.[0];\n if (!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 // Resize/compress via Clipboard's shared canvas pipeline so a file chosen\n // through this dialog gets the same treatment as a pasted/dropped image\n // instead of embedding the original (potentially multi-MB) file untouched.\n this.context.invoke('clipboard.compressAndRegister', file).then((blobUrl) => {\n if (this.context._alive === false) return;\n this._urlInput.value = blobUrl;\n }).catch((err) => {\n if (this.context._alive === false) return;\n // Compression failed (e.g. canvas unavailable) — fall back to embedding\n // the original file directly.\n console.warn('[AutumnNote] ImageDialog: image compression failed, using original file.', err);\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\n _onInsert() {\n const src = this._urlInput.value.trim();\n const alt = this._altInput.value.trim();\n const alignRadio = this._alignRow?.querySelector('input[name=\"an-img-align\"]:checked');\n const align = alignRadio ? /** @type {HTMLInputElement} */ (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 // Let callers make a deferred DOM change only after the user commits the\n // dialog. SlashMenu uses this to keep \"/image\" intact when the dialog is\n // cancelled and remove it atomically immediately before image insertion.\n const beforeInsert = this._beforeInsert;\n this._beforeInsert = null;\n beforeInsert?.();\n\n this.context.invoke('editor.insertImage', src, alt, align);\n this._close();\n }\n\n _close() {\n this._beforeInsert = null;\n super._close();\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 } from '../core/dom.js';\nimport { sanitiseUrl } from '../core/sanitise.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" 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\nexport class VideoDialog extends BaseDialog {\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n this._saveRange();\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, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, 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 this._firstInput = 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 const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());\n box.append(urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);\n\n // Live URL hint\n const d0 = on(urlInput, 'input', () => {\n const info = this._parseVideoUrl(urlInput.value.trim());\n let hint = '';\n if (info) { hint = this.context.locale.videoDialog.detected(info.type); }\n else if (urlInput.value) { hint = this.context.locale.videoDialog.unknownFormat; }\n hintEl.textContent = hint;\n });\n const d4 = on(urlInput, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Enter') { e.preventDefault(); this._onInsert(); } });\n this._disposers.push(d0, 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, Number.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 // ---------------------------------------------------------------------------\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 if (!sanitiseUrl(url, { media: true })) return null;\n\n // YouTube watch: https://www.youtube.com/watch?v=ID\n const ytWatch = /(?:youtube\\.com\\/watch\\?(?:.*&)?v=|youtube\\.com\\/embed\\/)([a-zA-Z0-9_-]{11})/.exec(url);\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 = /youtu\\.be\\/([a-zA-Z0-9_-]{11})/.exec(url);\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 = /youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]{11})/.exec(url);\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 = /vimeo\\.com\\/(\\d+)/.exec(url);\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?.type === 'Direct video') {\n const src = info.embedUrl.replaceAll('\"', '%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 = sanitiseUrl(url, { media: true });\n if (!safeSrc) return null;\n\n const escapedSrc = safeSrc.replaceAll('\"', '%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","/**\n * BaseResizer.js — Shared drag-to-resize overlay for selectable embeds.\n *\n * ImageResizer and VideoResizer were ~28% duplicate: identical overlay\n * construction, selection tracking, scroll/resize repositioning and drag maths,\n * differing only in what counts as a target and how the new size is applied.\n * Subclasses now supply just those differences via the hooks below.\n *\n * Mirrors the existing BaseDialog pattern used by the dialog modules.\n */\n\nimport { on } from '../core/dom.js';\n\n/**\n * Eight handle positions. 'pos' is used as CSS class suffix and to determine\n * 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 BaseResizer {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n /** @type {HTMLElement|null} Currently selected element */\n this._active = null;\n /** @type {HTMLElement|null} */\n this._overlay = null;\n this._disposers = [];\n this._positionRaf = null;\n /** @type {{l:number,t:number,w:number,h:number}|null} Last written overlay box */\n this._lastOverlayPos = null;\n }\n\n // ---------------------------------------------------------------------------\n // Subclass hooks\n // ---------------------------------------------------------------------------\n\n /** CSS class for the overlay element. @returns {string} */\n get _overlayClass() { return 'an-resizer'; }\n\n /** CSS class applied to the selected element. @returns {string} */\n get _selectedClass() { return 'an-selected'; }\n\n /**\n * Resolves an event target to a resizable element.\n * @param {EventTarget|null} _el\n * @returns {HTMLElement|null}\n */\n _findTarget(_el) { return null; }\n\n /**\n * Natural starting dimensions of the target, used as the drag baseline.\n * @param {HTMLElement} _target\n * @returns {{ w: number, h: number }}\n */\n _getStartSize(_target) { return { w: 0, h: 0 }; }\n\n /** Smallest allowed dimensions. @returns {{ minW: number, minH: number }} */\n _getMinSize() { return { minW: 20, minH: 20 }; }\n\n /**\n * Writes the new size to the target (and any inner embed).\n * @param {HTMLElement} _target\n * @param {number} _w\n * @param {number} _h\n */\n _applySize(_target, _w, _h) {}\n\n /**\n * Additional listeners a subclass needs; the returned disposers are torn down\n * with the rest in destroy().\n * @returns {Array<() => void>}\n */\n _extraListeners() { return []; }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\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 target = this._findTarget(e.target);\n if (target) this._select(target);\n }),\n on(document, 'click', (e) => this._onDocClick(e)),\n on(globalThis, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n on(globalThis, 'resize', onWindowResize, { passive: true }),\n on(editable, 'scroll', () => this._updateOverlayPosition(), { passive: true }),\n ...this._extraListeners(),\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 this._overlay?.remove();\n this._overlay = null;\n }\n\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** Re-sync overlay position (call after external size changes). */\n updateOverlay() {\n this._updateOverlayPosition();\n }\n\n /** Programmatically clear the current selection. */\n deselect() {\n this._deselect();\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n _buildOverlay() {\n const overlay = document.createElement('div');\n overlay.className = this._overlayClass;\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 // Pointer events rather than mouse events, so the same code path serves\n // mouse, touch and pen. The handles also set `touch-action: none` in\n // CSS — without it a touch drag is claimed by the browser as a scroll\n // gesture and the pointer stream is cancelled before it starts.\n on(h, 'pointerdown', (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 target = this._findTarget(e.target);\n if (target) {\n // Prevent the browser from dropping the text selection / showing its own\n // native resize affordance.\n e.preventDefault();\n this._select(target);\n }\n }\n\n _onDocClick(e) {\n if (!this._active) return;\n if (this._active.contains(e.target)) return;\n if (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(target) {\n if (this._active && this._active !== target) {\n this._active.classList.remove(this._selectedClass);\n }\n this._active = target;\n this._lastOverlayPos = null; // invalidate position cache on new selection\n target.classList.add(this._selectedClass);\n this._updateOverlayPosition();\n this._overlay.style.display = 'block';\n }\n\n _deselect() {\n if (this._active) {\n this._active.classList.remove(this._selectedClass);\n this._active = 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._active || !this._overlay) return;\n const offsetParent = this._overlay.offsetParent || this._container;\n const containerRect = offsetParent.getBoundingClientRect();\n const rect = this._active.getBoundingClientRect();\n\n // Skip DOM writes when position hasn't changed (common during non-scroll rAF ticks)\n const p = this._lastOverlayPos;\n if (p?.l === rect.left && p.t === rect.top && p.w === rect.width && p.h === rect.height) return;\n this._lastOverlayPos = { l: rect.left, t: rect.top, w: rect.width, h: rect.height };\n\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 target = this._active;\n if (!target) return;\n\n const startX = e.clientX;\n const startY = e.clientY;\n const { w: startW, h: startH } = this._getStartSize(target);\n const { minW, minH } = this._getMinSize();\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(minW, startW + dx);\n if (pos.includes('w')) newW = Math.max(minW, startW - dx);\n if (pos.includes('s')) newH = Math.max(minH, startH + dy);\n if (pos.includes('n')) newH = Math.max(minH, 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(minH, Math.round(newW / aspectRatio));\n } else {\n newW = Math.min(Math.max(minW, Math.round(newH * aspectRatio)), maxW);\n newH = Math.max(minH, Math.round(newW / aspectRatio));\n }\n }\n\n this._applySize(target, newW, newH);\n this._updateOverlayPosition();\n });\n };\n\n const stop = () => {\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerup', onUp);\n document.removeEventListener('pointercancel', onUp);\n };\n\n const onUp = () => {\n if (raf !== null) { cancelAnimationFrame(raf); raf = null; }\n stop();\n this._dragDisposers = null;\n this.context.invoke('editor.afterCommand');\n };\n\n document.addEventListener('pointermove', onMove);\n document.addEventListener('pointerup', onUp);\n // A touch drag interrupted by the system (incoming call, gesture takeover)\n // ends with pointercancel and no pointerup, which would otherwise leave the\n // move listener attached for the rest of the session.\n document.addEventListener('pointercancel', onUp);\n // Track these so destroy() can clean them up if called during an active drag\n this._dragDisposers = [stop];\n }\n}\n","// ImageResizer.js - Interactive resize handles for selected images in the editor\nimport { BaseResizer } from './BaseResizer.js';\n\nexport class ImageResizer extends BaseResizer {\n get _overlayClass() { return 'an-image-resizer'; }\n get _selectedClass() { return 'an-image-selected'; }\n\n /** @param {EventTarget|null} el @returns {HTMLImageElement|null} */\n _findTarget(el) {\n return /** @type {HTMLImageElement|null} */ (\n el instanceof Element ? el.closest('img') : null\n );\n }\n\n /** @param {HTMLImageElement} img */\n _getStartSize(img) {\n return {\n w: img.offsetWidth || img.naturalWidth || 100,\n h: img.offsetHeight || img.naturalHeight || 100,\n };\n }\n\n _getMinSize() {\n const min = this.context.options?.minImageSize ?? 20;\n return { minW: min, minH: min };\n }\n\n /** @param {HTMLImageElement} img @param {number} w @param {number} h */\n _applySize(img, w, h) {\n img.style.width = `${w}px`;\n img.style.height = `${h}px`;\n }\n\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLImageElement|null} */\n getActiveImage() {\n return /** @type {HTMLImageElement|null} */ (this._active);\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';\nimport { BaseResizer } from './BaseResizer.js';\n\nexport class VideoResizer extends BaseResizer {\n get _overlayClass() { return 'an-video-resizer'; }\n get _selectedClass() { return 'an-video-selected'; }\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|null} el\n * @returns {HTMLElement|null}\n */\n _findTarget(el) {\n if (!el || !(el instanceof Element)) return null;\n if (el.classList?.contains('an-video-wrapper')) return /** @type {HTMLElement} */ (el);\n return /** @type {HTMLElement|null} */ (el.closest('.an-video-wrapper'));\n }\n\n /** @param {HTMLElement} wrapper */\n _getStartSize(wrapper) {\n return { w: wrapper.offsetWidth || 560, h: wrapper.offsetHeight || 315 };\n }\n\n _getMinSize() {\n return { minW: 80, minH: 45 };\n }\n\n /** @param {HTMLElement} wrapper @param {number} w @param {number} h */\n _applySize(wrapper, w, h) {\n // Resize wrapper and inner embed via CSS only — attribute writes are redundant\n wrapper.style.width = `${w}px`;\n wrapper.style.height = `${h}px`;\n const embed = /** @type {HTMLElement|null} */ (wrapper.querySelector('iframe, video'));\n if (embed) {\n embed.style.width = `${w}px`;\n embed.style.height = `${h}px`;\n }\n }\n\n _extraListeners() {\n const editable = this.context.layoutInfo.editable;\n return [\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\n // ---------------------------------------------------------------------------\n // Public API used by other modules\n // ---------------------------------------------------------------------------\n\n /** @returns {HTMLElement|null} */\n getActiveWrapper() {\n return this._active;\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 = /** @type {Element} */ (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 = /** @type {Node|null} */ (/** @type {MouseEvent} */ (e).relatedTarget);\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\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?.parentNode) this._el.remove();\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 > globalThis.innerHeight - margin) {\n top = rect.top - tipH - margin;\n }\n if (left + tipW > globalThis.innerWidth - margin) {\n left = globalThis.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?.getAttribute('href');\n if (url) globalThis.open(url, '_blank', 'noopener,noreferrer');\n this._hide();\n }\n\n _copyLink() {\n const url = 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 ta.remove();\n });\n }\n // Brief visual feedback \n if (this._copyBtn) {\n this._copyBtn.classList.add('an-link-tooltip-btn--copied');\n setTimeout(() => 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 = globalThis.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 = globalThis.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","/**\n * BaseMediaTooltip.js — Shared hover-tooltip behaviour for media embeds.\n *\n * ImageTooltip and VideoTooltip duplicated their button factory, show/hide\n * timers and viewport-aware positioning (~22% of both files). Those pieces live\n * here; each subclass keeps only what genuinely differs — which element counts\n * as the target, which buttons the bar contains, and the actions behind them.\n *\n * Mirrors the existing BaseDialog / BaseResizer pattern.\n */\n\nimport { createElement, on } from '../core/dom.js';\n\n/** Delay before a hovered target shows its tooltip. */\nexport const SHOW_DELAY = 100;\n/** Grace period before a tooltip hides after the pointer leaves. */\nexport const HIDE_DELAY = 180;\n\nexport class BaseMediaTooltip {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n /** @type {HTMLElement|null} The tooltip bar */\n this._el = null;\n /** @type {HTMLElement|null} Currently hovered target */\n this._active = null;\n this._showTimer = null;\n this._hideTimer = null;\n this._disposers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Subclass hooks\n // ---------------------------------------------------------------------------\n\n /**\n * Whether `_scheduleHide` is allowed to start the hide countdown. Subclasses\n * override to pin the tooltip open (e.g. while a video preview is playing).\n * @returns {boolean}\n */\n _canHide() { return true; }\n\n /** Runs just before the tooltip is hidden, for subclass-specific teardown. */\n _beforeHide() {}\n\n // ---------------------------------------------------------------------------\n // Buttons\n // ---------------------------------------------------------------------------\n\n /**\n * Builds a tooltip button and registers its click disposer.\n * @param {string} icon - inline SVG markup\n * @param {string} title\n * @param {() => void} handler\n * @param {boolean} [isDanger]\n * @returns {HTMLElement}\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(target) {\n if (this._active === target && this._el.style.display !== 'none') return;\n clearTimeout(this._hideTimer);\n this._hideTimer = null;\n clearTimeout(this._showTimer);\n this._showTimer = setTimeout(() => {\n this._active = target;\n this._show(target);\n }, SHOW_DELAY);\n }\n\n _scheduleHide() {\n if (!this._canHide()) return;\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(_target) {\n this._el.style.display = 'flex';\n // Defer positioning: offsetWidth on a newly-visible element forces layout\n requestAnimationFrame(() => {\n if (this._active) this._positionNear(this._active);\n });\n }\n\n _hide() {\n this._beforeHide();\n this._el.style.display = 'none';\n this._active = 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 /**\n * Places the tooltip under the target, flipping above and clamping\n * horizontally when it would leave the viewport.\n * @param {HTMLElement} target\n */\n _positionNear(target) {\n const rect = target.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 > globalThis.innerHeight - margin) top = rect.top - tipH - margin;\n if (left + tipW > globalThis.innerWidth - margin) left = globalThis.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","// 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';\nimport { BaseMediaTooltip } from './BaseMediaTooltip.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\nexport class ImageTooltip extends BaseMediaTooltip {\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 = /** @type {Element} */ (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 = /** @type {Node|null} */ (/** @type {MouseEvent} */ (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 const et = /** @type {Node} */ (e.target);\n if (this._active && !this._active.contains(et) && !this._el.contains(et)) {\n this._hide();\n }\n }),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\n );\n\n return this;\n }\n\n destroy() {\n this._clearTimers();\n this._disposers.forEach((d) => d());\n this._disposers = [];\n this._el?.remove();\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 // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const img = this._active;\n if (!img) return;\n const target = /** @type {HTMLElement} */ (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._active) this._positionNear(this._active); });\n }\n\n _setCenter() {\n const img = this._active;\n if (!img) return;\n const target = /** @type {HTMLElement} */ (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._active) this._positionNear(this._active); });\n }\n\n _resetSize() {\n const img = this._active;\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._active) this._positionNear(this._active); });\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._active;\n if (!img) return;\n // Parse current rotation angle from inline transform\n const current = img.style.transform || '';\n const match = /rotate\\((-?[\\d.]+)deg\\)/.exec(current);\n const prev = match ? Number.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 if (cleaned) {\n img.style.transform = `${cleaned} rotate(${next}deg)`;\n } else {\n img.style.transform = next === 0 ? '' : `rotate(${next}deg)`;\n }\n this.context.invoke('editor.afterCommand');\n this.context.invoke('imageResizer.updateOverlay');\n requestAnimationFrame(() => { if (this._active) this._positionNear(this._active); });\n }\n\n _delete() {\n const img = this._active;\n if (!img) return;\n this._hide();\n this.context.invoke('imageResizer.deselect');\n const figure = img.closest('figure.an-figure');\n if (figure) {\n figure.remove();\n } else {\n img.remove();\n }\n this.context.invoke('editor.afterCommand');\n }\n\n _crop() {\n const img = this._active;\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._active;\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 = globalThis.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 = globalThis.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';\nimport { BaseMediaTooltip } from './BaseMediaTooltip.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\nexport class VideoTooltip extends BaseMediaTooltip {\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 target = /** @type {Element} */ (e.target);\n const wrapper = 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 = /** @type {MouseEvent} */ (e).relatedTarget;\n if (!to || (!editable.contains(/** @type {Node} */ (to)) && !this._el.contains(/** @type {Node} */ (to)))) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n const target = /** @type {Node} */ (e.target);\n if (\n this._active &&\n !this._active.contains(target) &&\n !this._el.contains(target)\n ) {\n this._hide();\n }\n }),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\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 this._el?.remove();\n this._el = null;\n }\n\n // ---------------------------------------------------------------------------\n // Base hooks — keep the bar pinned while a preview is playing\n // ---------------------------------------------------------------------------\n\n /** @returns {boolean} */\n _canHide() { return !this._previewMode; }\n\n _beforeHide() {\n if (this._previewMode) this._exitPreview();\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 // Actions\n // ---------------------------------------------------------------------------\n\n _setFloat(value) {\n const wrapper = this._active;\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._active) this._positionNear(this._active); });\n }\n\n _setCenter() {\n const wrapper = this._active;\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._active) this._positionNear(this._active); });\n }\n\n _resetSize() {\n const wrapper = this._active;\n if (!wrapper) return;\n const embed = /** @type {HTMLElement|null} */ (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._active) this._positionNear(this._active); });\n }\n\n _delete() {\n const wrapper = this._active;\n if (!wrapper) return;\n this._hide();\n this.context.invoke('videoResizer.deselect');\n wrapper.remove();\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._active;\n if (!wrapper) return;\n this._previewMode = true;\n\n // Hide the shield so the iframe / video receives pointer events directly\n const shield = /** @type {HTMLElement|null} */ (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._active;\n if (wrapper) {\n // Restore the shield\n const shield = /** @type {HTMLElement|null} */ (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","/**\n * table-icons.js - Inline SVG glyphs for the table tooltip's action bar.\n *\n * Kept out of TableTooltip.js because the markup is ~9 KB of static data that\n * obscures the module's actual logic; nothing here has behaviour.\n */\n\nexport const 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 cellShade: `<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=\"M19 11L8.93 3.36a1 1 0 0 0-1.29.08L3.22 7.8a1 1 0 0 0-.07 1.29L11 20\"/><path d=\"m5 14 5-5\"/><path d=\"M22 22a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2c0-1.5 2.5-5 3.5-5s3.5 3.5 3.5 5z\"/></svg>`,\n borderColor: `<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=\"14\" rx=\"1\"/><line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\" stroke-width=\"1.5\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"17\" stroke-width=\"1.5\"/><path d=\"M3 21h18\" stroke-width=\"3\"/></svg>`,\n alignLeft: `<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=\"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\"/></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\"><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"17\" y1=\"12\" x2=\"7\" y2=\"12\"/><line x1=\"19\" y1=\"18\" x2=\"5\" y2=\"18\"/></svg>`,\n alignRight: `<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=\"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\"/></svg>`,\n alignJustify: `<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=\"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\"/></svg>`,\n headerRow: `<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\"/><rect x=\"3\" y=\"3\" width=\"18\" height=\"8\" rx=\"1\" fill=\"currentColor\" opacity=\"0.2\"/><line x1=\"3\" y1=\"11\" x2=\"21\" y2=\"11\"/><line x1=\"3\" y1=\"16\" x2=\"21\" y2=\"16\"/><line x1=\"9\" y1=\"11\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"11\" x2=\"15\" y2=\"21\"/></svg>`,\n sortAsc: `<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=\"6\" x2=\"11\" y2=\"6\"/><line x1=\"4\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"13\" y2=\"18\"/><path d=\"M15 9l3-3 3 3\"/><line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n sortDesc: `<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=\"6\" x2=\"13\" y2=\"6\"/><line x1=\"4\" y1=\"12\" x2=\"11\" y2=\"12\"/><line x1=\"4\" y1=\"18\" x2=\"11\" y2=\"18\"/><path d=\"M15 15l3 3 3-3\"/><line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n exportCSV: `<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 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>`,\n cellPadding: `<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\"/><rect x=\"7\" y=\"7\" width=\"10\" height=\"10\" rx=\"0.5\" stroke-dasharray=\"2 1.5\"/></svg>`,\n};\n","/**\n * table-grid.js - Geometry helpers for tables inside the editor.\n *\n * A table's DOM order is not its visual order once colspan/rowspan are in play,\n * so every structural operation (insert, delete, merge, sort) needs to reason\n * about the *visual* grid rather than about `row.cells` indices. These helpers\n * are pure functions of the table element, which keeps them independently\n * testable and free of any tooltip state.\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?.tagName === 'TD' || next?.tagName === 'TH') ? /** @type {HTMLTableCellElement} */ (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\nexport { getVisualColIndex, getCellAtVisualCol, getCellAfterVisualCol, buildGridMap };\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';\nimport { ICONS } from './table-icons.js';\nimport {\n getVisualColIndex,\n getCellAtVisualCol,\n getCellAfterVisualCol,\n buildGridMap,\n} from './table-grid.js';\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 200;\n\nconst SHADE_PRESETS = [\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\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 shade popover\n this._shadePopover = null;\n this._shadeTitleEl = null;\n this._shadeColorStrip = null;\n // Border color popover\n this._borderColorPopover = null;\n this._borderColorTitleEl = null;\n this._borderColorStrip = null;\n this._borderColorNoBtn = 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 this._shadePopover = this._buildCellShadePopover();\n document.body.appendChild(this._shadePopover);\n\n this._borderColorPopover = this._buildBorderColorPopover();\n document.body.appendChild(this._borderColorPopover);\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 on(editable, 'mouseover', (e) => {\n if (this.context.layoutInfo.container.classList.contains('an-disabled')) return;\n const table = /** @type {Element} */ (e.target)?.closest('table');\n if (table && editable.contains(table)) {\n const cell = /** @type {Element} */ (e.target)?.closest('td, th');\n if (cell) {\n this._activeCell = cell;\n this._syncShadeStrip();\n }\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 = /** @type {Node|null} */ (/** @type {MouseEvent} */ (e).relatedTarget);\n if (!to || (\n !editable.contains(to) &&\n !this._el.contains(to) &&\n !this._sizePopover?.contains(to)\n )) {\n this._scheduleHide();\n }\n }, { passive: true }),\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._selectMode && this._activeTable?.contains(et)) return;\n if (this._activeTable &&\n !this._activeTable.contains(et) &&\n !this._el.contains(et) &&\n !this._sizePopover?.contains(et) &&\n !this._shadePopover?.contains(et) &&\n !this._borderColorPopover?.contains(et)) {\n this._hide();\n }\n }),\n // Sync shade strip whenever selection moves to a different cell\n on(document, 'selectionchange', () => this._syncShadeStrip()),\n // Hide when the page scrolls or resizes — the tooltip position becomes stale\n on(globalThis, 'scroll', () => this._hide(), { passive: true }),\n on(globalThis, 'resize', () => this._hide(), { passive: true }),\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 // Right edge of a merged cell = last spanned column, not the start column\n _colIdx = getVisualColIndex(_nearCell) + (_nearCell.colSpan || 1) - 1;\n // Cache non-merged cells at that column — merged cells cannot be individually\n // resized per column (F-1: colSpan > 1 distributes width across all spanned cols)\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 // Use the actual column width from a non-merged cell; fall back to per-column estimate\n _startW = _colCells.length > 0\n ? _colCells[0].offsetWidth\n : Math.max(30, Math.round(_nearCell.offsetWidth / (_nearCell.colSpan || 1)));\n document.body.style.cursor = 'col-resize';\n } else {\n // Bottom edge of a merged cell = last spanned row, not the cell's own <tr>\n const tr = _nearCell.closest('tr');\n const rowStart = tr ? Array.from(_table.rows).indexOf(tr) : 0;\n const lastRowIdx = rowStart + (_nearCell.rowSpan || 1) - 1;\n _row = _table.rows[lastRowIdx] || 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?.parentNode) this._el.remove();\n this._el = null;\n if (this._sizePopover?.parentNode) {\n this._sizePopover.remove();\n }\n this._sizePopover = null;\n if (this._shadePopover?.parentNode) {\n this._shadePopover.remove();\n }\n this._shadePopover = null;\n if (this._borderColorPopover?.parentNode) {\n this._borderColorPopover.remove();\n }\n this._borderColorPopover = 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 el.appendChild(this._makeBtn(ICONS.sortAsc, L.sortAsc, () => this._sortColumn('asc')));\n el.appendChild(this._makeBtn(ICONS.sortDesc, L.sortDesc, () => this._sortColumn('desc')));\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 // Cell text alignment\n el.appendChild(this._makeBtn(ICONS.alignLeft, L.cellAlignLeft, () => this._applyCellAlign('left')));\n el.appendChild(this._makeBtn(ICONS.alignCenter, L.cellAlignCenter, () => this._applyCellAlign('center')));\n el.appendChild(this._makeBtn(ICONS.alignRight, L.cellAlignRight, () => this._applyCellAlign('right')));\n el.appendChild(this._makeBtn(ICONS.alignJustify, L.cellAlignJustify, () => this._applyCellAlign('justify')));\n el.appendChild(this._makeBtn(ICONS.headerRow, L.toggleHeaderRow, () => this._toggleHeaderRow()));\n\n el.appendChild(this._sep());\n\n // Cell background shading — uses color-strip variant like foreColor/hiliteColor buttons\n const shadeBtn = createElement('button', {\n type: 'button',\n class: 'an-link-tooltip-btn an-link-tooltip-btn--shade',\n title: L.cellBackground,\n });\n const shadeSvgWrap = createElement('span', { class: 'an-bubble-btn-svg' });\n shadeSvgWrap.innerHTML = ICONS.cellShade;\n const shadeStrip = createElement('span', { class: 'an-link-tooltip-color-strip' });\n shadeBtn.appendChild(shadeSvgWrap);\n shadeBtn.appendChild(shadeStrip);\n this._shadeColorStrip = shadeStrip;\n this._disposers.push(on(shadeBtn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._openCellShadePopover();\n }));\n el.appendChild(shadeBtn);\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 el.appendChild(this._makeBtn(ICONS.cellPadding, L.cellPadding, () => this._openSizePopover('cellPadding')));\n\n // Table border color button — color-strip variant like shade button\n const borderColorBtn = createElement('button', {\n type: 'button',\n class: 'an-link-tooltip-btn an-link-tooltip-btn--shade',\n title: L.tableBorderColor,\n });\n const borderColorSvgWrap = createElement('span', { class: 'an-bubble-btn-svg' });\n borderColorSvgWrap.innerHTML = ICONS.borderColor;\n const borderColorStrip = createElement('span', { class: 'an-link-tooltip-color-strip' });\n borderColorBtn.appendChild(borderColorSvgWrap);\n borderColorBtn.appendChild(borderColorStrip);\n this._borderColorStrip = borderColorStrip;\n this._disposers.push(on(borderColorBtn, 'click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._openBorderColorPopover();\n }));\n el.appendChild(borderColorBtn);\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 el.appendChild(this._sep());\n el.appendChild(this._makeBtn(ICONS.exportCSV, L.exportCSV, () => this._exportTableCSV()));\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 if (this._shadePopover && this._shadePopover.style.display !== 'none') return;\n if (this._borderColorPopover && this._borderColorPopover.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 this._syncShadeStrip();\n this._syncBorderColorStrip();\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 _syncShadeStrip() {\n if (!this._shadeColorStrip || !this._el || this._el.style.display === 'none') return;\n const cell = this._getCell();\n this._shadeColorStrip.style.background = cell?.style.backgroundColor || 'transparent';\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 this._hideBorderColorPopover();\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 > globalThis.innerWidth - margin) left = globalThis.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 = globalThis.getSelection();\n if (sel?.rangeCount) {\n let container = sel.getRangeAt(0).commonAncestorContainer;\n if (container.nodeType === 3) container = container.parentElement;\n const cellFromSel = /** @type {Element} */ (container)?.closest('td, th');\n if (cellFromSel && this._activeTable?.contains(cellFromSel)) {\n return cellFromSel;\n }\n }\n return this._activeCell\n || 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?.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 if (position === 'above') return ri < bi ? r : best;\n return ri > bi ? r : best;\n }, selectedRows[0]);\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?.style.width) td.style.width = ref.style.width;\n if (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.after(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.remove());\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.remove());\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 = globalThis.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.style.height = '';\n first.style.minHeight = '';\n\n // Merge content: collect non-empty inner HTML, join with <br> separator\n const parts = rectCells\n .map((c) => c.innerHTML.replace(/^(<br\\s*\\/?>|\\s)+$/i, '').trim())\n .filter((h) => h !== '');\n first.innerHTML = parts.length ? parts.join('<br>') : '<br>';\n\n rectCells.slice(1).forEach((c) => {\n const row = c.parentElement;\n c.remove();\n // Remove the parent <tr> if it is now completely empty\n if (row && row.cells.length === 0) row.remove();\n });\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.remove();\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 (&nbsp;); 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?.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 = /** @type {HTMLInputElement} */ (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 = Number.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 const ke = /** @type {KeyboardEvent} */ (e);\n if (ke.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (ke.key === 'Escape') this._hideSizePopover();\n });\n const d4 = on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._sizePopover &&\n this._sizePopover.style.display !== 'none' &&\n !this._sizePopover.contains(et) &&\n !this._el.contains(et)) {\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 ? (Number.parseInt(firstCell.style.borderWidth, 10) ||\n Number.parseInt(globalThis.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 = String(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 if (type === 'cellPadding') {\n const cells = this._getSelectedCells();\n const firstCell = cells[0] || this._getCell();\n const currentPad = firstCell\n ? (Number.parseInt(firstCell.style.padding, 10) ||\n Number.parseInt(firstCell.style.paddingTop, 10) || 4)\n : 4;\n this._sizeTitleEl.textContent = this.context.locale.tooltips.table.cellPaddingPx;\n this._sizeInputEl.min = '0';\n this._sizeInputEl.max = '40';\n this._sizeInputEl.value = String(currentPad);\n this._sizeApply = (val) => {\n const activeCells = this._getSelectedCells();\n activeCells.forEach((c) => { if (c) c.style.padding = `${val}px`; });\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 if (isCol) {\n this._sizeInputEl.value = cell.offsetWidth || 120;\n } else {\n const refRow = cell.closest('tr');\n this._sizeInputEl.value = refRow ? (refRow.offsetHeight || 40) : 40;\n }\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 > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;\n if (top + ph > globalThis.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 // ---------------------------------------------------------------------------\n // Colour popovers (cell shading + table border colour)\n // ---------------------------------------------------------------------------\n\n /**\n * Builds one of the two colour popovers. Both are the same widget — a preset\n * palette, a \"no colour\" reset row, and a custom `<input type=\"color\">` — and\n * they were previously two near-identical 55-line methods, so a fix applied\n * to one silently missed the other. They differ only in the swatch the custom\n * input starts on and in what the chosen colour is applied to.\n *\n * `getPopover` is read lazily rather than closed over: `destroy()` nulls the\n * field, and the deferred handlers must see that instead of holding the\n * detached element alive.\n *\n * @param {object} config\n * @param {string} config.defaultColor - initial value of the custom input\n * @param {(color: string) => void} config.apply - called with '' to clear\n * @param {() => HTMLElement|null} config.getPopover\n * @param {() => void} config.hide\n * @returns {{ el: HTMLElement, titleEl: HTMLElement, noColorBtn: HTMLElement }}\n */\n _buildColorPopover({ defaultColor, apply, getPopover, hide }) {\n const pop = createElement('div', { class: 'an-cell-shade-popover' });\n pop.style.display = 'none';\n\n const titleEl = createElement('div', { class: 'an-size-popover-title' });\n pop.appendChild(titleEl);\n\n // 24-color palette — reuse existing CSS classes\n const palette = createElement('div', { class: 'an-context-color-palette' });\n SHADE_PRESETS.forEach((color) => {\n const sw = createElement('div', { class: 'an-context-color-swatch', title: color });\n sw.style.background = color;\n this._disposers.push(on(sw, 'click', (e) => {\n e.stopPropagation();\n apply(color);\n }));\n palette.appendChild(sw);\n });\n pop.appendChild(palette);\n\n // Reset row — clears the colour\n const noColorRow = createElement('div', { class: 'an-context-color-custom' });\n const noColorBtn = createElement('button', { type: 'button', class: 'an-shade-no-color' });\n this._disposers.push(on(noColorBtn, 'click', () => apply('')));\n noColorRow.appendChild(noColorBtn);\n pop.appendChild(noColorRow);\n\n // Custom color input\n const customRow = createElement('div', { class: 'an-context-color-custom' });\n const colorInput = /** @type {HTMLInputElement} */ (createElement('input', { type: 'color', class: 'an-shade-color-input', value: defaultColor }));\n const customLabel = createElement('span');\n customLabel.textContent = this.context.locale.contextMenu.customColorLabel;\n this._disposers.push(on(colorInput, 'change', () => apply(colorInput.value)));\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n pop.appendChild(customRow);\n\n // Prevent mousedown from collapsing editor selection; keep tooltip alive while hovering\n this._disposers.push(\n on(pop, 'mousedown', (e) => e.preventDefault()),\n on(pop, 'mouseenter', () => this._clearTimers()),\n on(pop, 'mouseleave', () => this._scheduleHide()),\n // Close on outside click\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n const current = getPopover();\n if (current &&\n current.style.display !== 'none' &&\n !current.contains(et) &&\n !this._el?.contains(et)) {\n hide();\n }\n }),\n );\n\n return { el: pop, titleEl, noColorBtn };\n }\n\n /**\n * Shows a colour popover under the tooltip, flipping above it when there is\n * no room below. Measurement has to wait a frame because the popover is\n * display:none until now and would otherwise report zero size.\n * @param {() => HTMLElement|null} getPopover\n */\n _showColorPopover(getPopover) {\n const pop = getPopover();\n if (!pop) return;\n pop.style.display = 'block';\n requestAnimationFrame(() => {\n const current = getPopover();\n if (!current || !this._el) return;\n const pw = current.offsetWidth || 170;\n const ph = current.offsetHeight || 120;\n const tipRect = this._el.getBoundingClientRect();\n let left = tipRect.left;\n let top = tipRect.bottom + 6;\n if (left + pw > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;\n if (top + ph > globalThis.innerHeight - 8) top = tipRect.top - ph - 6;\n current.style.left = `${Math.max(8, left)}px`;\n current.style.top = `${Math.max(8, top)}px`;\n });\n }\n\n // --- Cell background shade ---\n\n _buildCellShadePopover() {\n const { el, titleEl, noColorBtn } = this._buildColorPopover({\n defaultColor: '#ffffff',\n apply: (color) => this._applyCellShade(color),\n getPopover: () => this._shadePopover,\n hide: () => this._hideCellShadePopover(),\n });\n this._shadeTitleEl = titleEl;\n this._shadeNoBtn = noColorBtn;\n return el;\n }\n\n _openCellShadePopover() {\n if (!this._shadePopover) return;\n const L = this.context.locale.tooltips.table;\n if (this._shadeTitleEl) this._shadeTitleEl.textContent = L.cellBackground;\n if (this._shadeNoBtn) this._shadeNoBtn.textContent = L.noShading;\n this._showColorPopover(() => this._shadePopover);\n }\n\n _hideCellShadePopover() {\n if (this._shadePopover) this._shadePopover.style.display = 'none';\n }\n\n _applyCellShade(color) {\n const cells = this._selectMode ? this._selectedCells : [this._getCell()];\n cells.forEach((cell) => {\n if (cell) cell.style.backgroundColor = color;\n });\n // Update the color strip on the shade button to reflect the applied color\n if (this._shadeColorStrip) {\n this._shadeColorStrip.style.background = color || 'transparent';\n }\n this._hideCellShadePopover();\n this.context.invoke('editor.afterCommand');\n }\n\n // --- Table border colour ---\n\n _buildBorderColorPopover() {\n const { el, titleEl, noColorBtn } = this._buildColorPopover({\n defaultColor: '#000000',\n apply: (color) => this._applyBorderColor(color),\n getPopover: () => this._borderColorPopover,\n hide: () => this._hideBorderColorPopover(),\n });\n this._borderColorTitleEl = titleEl;\n this._borderColorNoBtn = noColorBtn;\n return el;\n }\n\n _openBorderColorPopover() {\n if (!this._borderColorPopover) return;\n const L = this.context.locale.tooltips.table;\n if (this._borderColorTitleEl) this._borderColorTitleEl.textContent = L.tableBorderColor;\n if (this._borderColorNoBtn) this._borderColorNoBtn.textContent = L.noBorderColor;\n this._showColorPopover(() => this._borderColorPopover);\n }\n\n _hideBorderColorPopover() {\n if (this._borderColorPopover) this._borderColorPopover.style.display = 'none';\n }\n\n _applyBorderColor(color) {\n const table = this._activeTable;\n if (!table) return;\n Array.from(table.querySelectorAll('td, th')).forEach((c) => { c.style.borderColor = color; });\n if (this._borderColorStrip) {\n this._borderColorStrip.style.background = color || 'transparent';\n }\n this._hideBorderColorPopover();\n this.context.invoke('editor.afterCommand');\n }\n\n _syncBorderColorStrip() {\n if (!this._borderColorStrip || !this._el || this._el.style.display === 'none') return;\n const firstCell = this._activeTable?.querySelector('td, th');\n this._borderColorStrip.style.background = firstCell?.style.borderColor || 'transparent';\n }\n\n // ---------------------------------------------------------------------------\n // Cell text alignment\n // ---------------------------------------------------------------------------\n\n _applyCellAlign(align) {\n const cells = this._getSelectedCells();\n cells.forEach((c) => { if (c) c.style.textAlign = align; });\n this.context.invoke('editor.afterCommand');\n }\n\n // ---------------------------------------------------------------------------\n // Toggle header row\n // ---------------------------------------------------------------------------\n\n _toggleHeaderRow() {\n const table = this._activeTable;\n if (!table) return;\n const firstRow = table.querySelector('tr');\n if (!firstRow) return;\n\n const isInThead = firstRow.closest('thead') !== null;\n\n if (isInThead) {\n // Convert th → td and move row to tbody\n let tbody = table.querySelector('tbody');\n if (!tbody) {\n tbody = document.createElement('tbody');\n table.appendChild(tbody);\n }\n Array.from(firstRow.cells).forEach((cell) => {\n const td = document.createElement('td');\n td.innerHTML = cell.innerHTML;\n td.style.cssText = cell.style.cssText;\n firstRow.replaceChild(td, cell);\n });\n tbody.insertBefore(firstRow, tbody.firstChild);\n const thead = table.querySelector('thead');\n if (thead && thead.rows.length === 0) thead.remove();\n } else {\n // Convert td → th and move row to thead\n let thead = table.querySelector('thead');\n if (!thead) {\n thead = document.createElement('thead');\n table.insertBefore(thead, table.firstChild);\n }\n Array.from(firstRow.cells).forEach((cell) => {\n const th = document.createElement('th');\n th.innerHTML = cell.innerHTML;\n th.style.cssText = cell.style.cssText;\n firstRow.replaceChild(th, cell);\n });\n thead.appendChild(firstRow);\n }\n\n this.context.invoke('editor.afterCommand');\n }\n\n _sortColumn(direction) {\n const table = this._activeTable;\n if (!table) return;\n const cell = this._getCell();\n if (!cell) return;\n const colIdx = getVisualColIndex(cell);\n if (colIdx === -1) return;\n const tbody = table.querySelector('tbody') || table;\n const rows = Array.from(tbody.querySelectorAll(':scope > tr'));\n if (rows.length < 2) return;\n rows.sort((a, b) => {\n const aCell = getCellAtVisualCol(a, colIdx);\n const bCell = getCellAtVisualCol(b, colIdx);\n const aText = (aCell?.textContent || '').trim();\n const bText = (bCell?.textContent || '').trim();\n const aNum = parseFloat(aText);\n const bNum = parseFloat(bText);\n if (!isNaN(aNum) && !isNaN(bNum)) {\n return direction === 'asc' ? aNum - bNum : bNum - aNum;\n }\n return direction === 'asc'\n ? aText.localeCompare(bText)\n : bText.localeCompare(aText);\n });\n rows.forEach((row) => tbody.appendChild(row));\n this._markSortIndicator(table, colIdx, direction);\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Marks the header cell of the sorted column with `an-sort-asc`/`an-sort-desc`\n * so the active sort column and direction are visible, and clears any previous\n * indicator. No-op for tables without a `<thead>` (no header row to mark).\n * @param {HTMLTableElement} table\n * @param {number} colIdx\n * @param {'asc'|'desc'} direction\n */\n _markSortIndicator(table, colIdx, direction) {\n const thead = table.querySelector('thead');\n if (!thead) return;\n thead.querySelectorAll('.an-sort-asc, .an-sort-desc').forEach((el) => {\n el.classList.remove('an-sort-asc', 'an-sort-desc');\n });\n const headerRow = thead.querySelector('tr');\n if (!headerRow) return;\n const headerCell = getCellAtVisualCol(headerRow, colIdx);\n if (headerCell) headerCell.classList.add(direction === 'asc' ? 'an-sort-asc' : 'an-sort-desc');\n }\n\n _exportTableCSV() {\n const table = this._activeTable;\n if (!table) return;\n const rows = Array.from(table.querySelectorAll('tr'));\n const csv = rows.map((row) =>\n Array.from(row.querySelectorAll('td, th'))\n .map((cell) => {\n const text = (cell.textContent || '').trim().replace(/\"/g, '\"\"');\n return `\"${text}\"`;\n })\n .join(',')\n ).join('\\n');\n const blob = new Blob(['' + csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'table.csv';\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(url);\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 lineNumbers: `<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=\"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 6h1v4\"/><path d=\"M4 10h2\"/><path d=\"M6 18H4c0-1 2-2 2-3s-1-2-2-2\"/></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._wrapBtn = null;\n this._lineNumbersBtn = 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 = /** @type {Element} */ (e.target)?.closest('pre');\n if (pre && editable.contains(pre)) {\n this._scheduleShow(pre);\n }\n }),\n on(editable, 'mouseout', (e) => {\n const to = /** @type {Node|null} */ (/** @type {MouseEvent} */ (e).relatedTarget);\n if (!to || (!editable.contains(to) && !this._el.contains(to))) {\n this._scheduleHide();\n }\n }),\n on(document, 'click', (e) => {\n const et = /** @type {Node} */ (e.target);\n if (this._activePre &&\n !this._activePre.contains(et) &&\n !this._el.contains(et)) {\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 this._el?.remove();\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 = /** @type {HTMLSelectElement} */ (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'], ['scss', 'SCSS'],\n ['json', 'JSON'], ['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 // Toggle line numbers\n this._lineNumbersBtn = this._makeBtn(ICONS.lineNumbers, L.lineNumbers, () => this._toggleLineNumbers());\n el.appendChild(this._lineNumbersBtn);\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._syncLineNumbersBtn();\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 > globalThis.innerWidth - margin) left = globalThis.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 || globalThis.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 _syncLineNumbersBtn() {\n if (!this._activePre || !this._lineNumbersBtn) return;\n const on = this._activePre.classList.contains('an-code-line-numbers');\n this._lineNumbersBtn.classList.toggle('active', on);\n this._lineNumbersBtn.title = this.context.locale.tooltips.code.lineNumbers;\n }\n\n _syncLangSelect() {\n if (!this._activePre || !this._langSelect) return;\n const codeEl = this._activePre.querySelector('code');\n const fromAttr = this._activePre.dataset.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 (_) { void _; }\n ta.remove();\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 _toggleLineNumbers() {\n const pre = this._activePre;\n if (!pre) return;\n pre.classList.toggle('an-code-line-numbers');\n this._syncLineNumbersBtn();\n this.context.invoke('editor.afterCommand');\n }\n\n /**\n * Applies a language to a given <pre> element: sets classes, data-language,\n * and triggers Prism highlighting. Called by the auto-detect flow.\n * @param {HTMLElement} pre\n * @param {string} lang - Prism language identifier, e.g. 'javascript'\n */\n applyLanguage(pre, lang) {\n if (!pre || !lang) return;\n // Temporarily set activePre so _onLangChange can target it\n const savedPre = this._activePre;\n this._activePre = pre;\n if (this._langSelect) this._langSelect.value = lang;\n this._onLangChange();\n // Update the select to reflect the detected language when tooltip is shown\n if (this._langSelect) this._langSelect.value = lang;\n this._activePre = savedPre || pre;\n // Don't restore savedPre if it was null — keep `pre` as activePre so that\n // the tooltip select is correct the first time the user hovers over it.\n }\n\n _onLangChange() {\n const pre = this._activePre;\n if (!pre) return;\n const lang = this._langSelect.value;\n const _w = /** @type {any} */ (globalThis);\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.dataset.language = lang;\n } else {\n delete pre.dataset.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 _w.Prism.highlightElement(codeEl);\n this.context.invoke('editor.afterCommand');\n };\n\n if (lang) {\n if (_w.Prism !== undefined) {\n // Grammar already loaded — highlight immediately\n if (_w.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 (_w.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 const _w = /** @type {any} */ (globalThis);\n if (!this.context.options.codeHighlight || _w.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 = _w.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 _w = /** @type {any} */ (globalThis);\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 (_w.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', /** @type {EventListener} */ (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 pre.remove();\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, makeDraggable } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\n/**\n * Resolved emoji catalogue, shared by every editor instance on the page.\n * @type {{ EMOJI_CATS: Array, EMOJI_LIST: Array }|null}\n */\nlet _emojiData = null;\n/** @type {Promise<{ EMOJI_CATS: Array, EMOJI_LIST: Array }>|null} */\nlet _emojiDataPromise = null;\n\n/**\n * Loads the emoji catalogue on first use. The table is ~25 KB (≈6 KB gzip),\n * so it is split into its own chunk rather than shipped to every consumer —\n * including those whose toolbar never shows an emoji button.\n * @returns {Promise<{ EMOJI_CATS: Array, EMOJI_LIST: Array }>}\n */\nfunction loadEmojiData() {\n if (_emojiData) return Promise.resolve(_emojiData);\n _emojiDataPromise ??= import('./emoji-data.js').then((mod) => {\n _emojiData = { EMOJI_CATS: mod.EMOJI_CATS, EMOJI_LIST: mod.EMOJI_LIST };\n return _emojiData;\n });\n return _emojiDataPromise;\n}\n\n// ---------------------------------------------------------------------------\n// Dialog class\n// ---------------------------------------------------------------------------\n\nexport class EmojiDialog extends BaseDialog {\n _activeCat = 'all';\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n // Grid is built lazily in show() to avoid ~500 DOM nodes at load time.\n return this;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the picker, fetching the emoji catalogue chunk on first call.\n * Awaiting is optional — the dialog opens on its own once data arrives.\n * @returns {Promise<void>}\n */\n async show() {\n // Capture the caret before awaiting: the selection must be read while the\n // click that opened the dialog is still the current interaction.\n this._saveRange();\n\n if (!this._dialog) {\n const { EMOJI_CATS, EMOJI_LIST } = await loadEmojiData();\n // A second show() may have won the race while this one awaited.\n if (!this._dialog) {\n this._cats = EMOJI_CATS;\n this._list = EMOJI_LIST;\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\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 titleGroup = createElement('div', { class: 'an-dialog-title-group' });\n const iconEl = createElement('span', { class: 'an-dialog-icon an-dialog-icon--sm' });\n iconEl.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 13s1.5 2 4 2 4-2 4-2\"/><line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\"/><line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\"/></svg>`;\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n titleGroup.append(iconEl, title);\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '&times;';\n titleRow.append(titleGroup, closeBtn);\n\n // Search\n const searchInput = /** @type {HTMLInputElement} */ (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 this._cats.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = 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 this._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 this._firstInput = searchInput;\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 makeDraggable(titleRow, 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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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', /** @type {HTMLElement} */ (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 hCell = /** @type {HTMLElement} */ (cell);\n const matchCat = !cat || cat === 'all' || hCell.dataset.cat === cat;\n const matchQuery = !q || hCell.dataset.keywords.includes(q) || hCell.dataset.char === q;\n const visible = matchCat && matchQuery;\n hCell.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 /** @type {HTMLElement} */ (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 = globalThis.getSelection();\n let range = 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 = /** @type {Element|null} */ (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest('td, th');\n range.deleteContents();\n if (_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","/**\n * IconDialog.js - Browse and insert FontAwesome Free icons\n */\n\nimport { createElement, on, makeDraggable } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\n/** Fallback stylesheet URL when `options.fontAwesomeCDN` is absent. Mirrors settings.js. */\nconst FONT_AWESOME_CDN = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css';\n\n/**\n * Resolved icon catalogue, shared by every editor instance on the page.\n * @type {{ ICON_CATEGORIES: Array, ICON_LIST: Array }|null}\n */\nlet _iconData = null;\n/** @type {Promise<{ ICON_CATEGORIES: Array, ICON_LIST: Array }>|null} */\nlet _iconDataPromise = null;\n\n/**\n * Loads the icon catalogue on first use. Mirrors EmojiDialog's split: the table\n * is ~6 KB gzip of slugs that consumers without an icon button never render.\n * @returns {Promise<{ ICON_CATEGORIES: Array, ICON_LIST: Array }>}\n */\nfunction loadIconData() {\n if (_iconData) return Promise.resolve(_iconData);\n _iconDataPromise ??= import('./icon-data.js').then((mod) => {\n _iconData = { ICON_CATEGORIES: mod.ICON_CATEGORIES, ICON_LIST: mod.ICON_LIST };\n return _iconData;\n });\n return _iconDataPromise;\n}\n\nexport class IconDialog extends BaseDialog {\n _selectedIcon = null;\n _activeCat = 'all';\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n initialize() {\n // Neither the FA stylesheet nor the grid is needed until the dialog opens —\n // both are deferred to show() so merely mounting an editor makes no\n // third-party request and builds no ~250 icon cells.\n return this;\n }\n\n /**\n * Injects FA 6 Free CSS from a 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 * Opt out with `fontAwesomeAutoInject: false`, or point the request\n * somewhere self-hosted with `fontAwesomeCDN`.\n */\n _ensureFontAwesome() {\n if (this.context.options.fontAwesomeAutoInject === false) return;\n // Fall back to the default URL rather than the option value alone: modules\n // are constructible with a partial options object, and losing the glyphs\n // silently is worse than the request the consumer did not opt out of.\n const href = this.context.options.fontAwesomeCDN || FONT_AWESOME_CDN;\n if (!href) return;\n\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) => /** @type {HTMLLinkElement} */ (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 = href;\n link.crossOrigin = 'anonymous';\n link.referrerPolicy = 'no-referrer';\n document.head.appendChild(link);\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Opens the picker, fetching the icon catalogue chunk on first call.\n * Awaiting is optional — the dialog opens on its own once data arrives.\n * @returns {Promise<void>}\n */\n async show() {\n // Capture the caret before awaiting: the selection must be read while the\n // click that opened the dialog is still the current interaction.\n this._saveRange();\n this._ensureFontAwesome();\n\n if (!this._dialog) {\n const { ICON_CATEGORIES, ICON_LIST } = await loadIconData();\n // A second show() may have won the race while this one awaited.\n if (!this._dialog) {\n this._cats = ICON_CATEGORIES;\n this._list = ICON_LIST;\n this._dialog = this._buildDialog();\n document.body.appendChild(this._dialog);\n }\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 titleGroup = createElement('div', { class: 'an-dialog-title-group' });\n const iconEl = createElement('span', { class: 'an-dialog-icon an-dialog-icon--sm' });\n iconEl.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/></svg>`;\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.title;\n titleGroup.append(iconEl, title);\n const closeBtn = createElement('button', { type: 'button', class: 'an-icon-close', 'aria-label': L.close });\n closeBtn.innerHTML = '&times;';\n titleRow.append(titleGroup, closeBtn);\n\n // Search\n const searchInput = /** @type {HTMLInputElement} */ (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 this._firstInput = 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 this._cats.forEach(({ id, label }) => {\n const tab = createElement('button', { type: 'button', class: 'an-icon-cat', 'data-cat': id });\n tab.textContent = 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 this._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 = /** @type {HTMLSelectElement} */ (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 = /** @type {HTMLSelectElement} */ (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 = /** @type {HTMLOptionElement} */ (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 = /** @type {HTMLInputElement} */ (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 = /** @type {HTMLInputElement} */ (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 makeDraggable(titleRow, 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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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', /** @type {HTMLElement} */ (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 hCell = /** @type {HTMLElement} */ (cell);\n const name = hCell.dataset.name;\n const cellCat = hCell.dataset.cat;\n const matchesCat = !cat || cat === 'all' || cellCat === cat;\n const matchesQuery = !q || name.includes(q);\n const visible = matchesCat && matchesQuery;\n hCell.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 /** @type {HTMLElement} */ (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', /** @type {HTMLElement} */ (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?.value || 'fa-solid';\n const size = this._sizeSelect?.value || '1em';\n const useColor = this._useColorCb?.checked ?? false;\n const color = useColor ? (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?.value || 'fa-solid';\n const size = this._sizeSelect?.value || '';\n const useColor = this._useColorCb?.checked ?? false;\n const color = useColor ? (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 = globalThis.getSelection();\n let range = (sel?.rangeCount ?? 0) > 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 = /** @type {Element|null} */ (_sc.nodeType === 1 ? _sc : _sc.parentElement)\n ?.closest('td, th');\n range.deleteContents();\n if (_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?.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 _close() {\n this._selectedIcon = null;\n super._close();\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?.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)).catch(() => {});\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?.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?.editable;\n if (editable) {\n this._disposers.push(on(editable, 'contextmenu', (e) => this._onContextMenu(e)));\n }\n\n this._disposers.push(\n on(document, 'click', (e) => this._maybeHide(e)),\n on(document, 'keydown', (e) => { if (/** @type {KeyboardEvent} */ (e).key === 'Escape') this.hide(); }),\n on(globalThis, 'scroll', () => this.hide(), { passive: true }),\n );\n\n return this;\n }\n\n destroy() {\n this._menuDisposers.forEach((d) => { try { d(); } catch (_e) { void _e; } });\n this._menuDisposers = [];\n this._disposers.forEach((d) => { try { d(); } catch (_e) { void _e; } });\n this._disposers = [];\n if (this.el) this.el.remove();\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 = Number.parseFloat(this.el.style.left);\n const curTop = Number.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 = Number.parseFloat(this.el.style.left);\n const curTop = Number.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 = /** @type {HTMLInputElement} */ (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) ? `${rows} × ${cols}` : (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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 = /** @type {HTMLElement} */ (/** @type {Element} */ (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?.editable;\n if (editable && this._savedRange) {\n editable.focus();\n const sel = globalThis.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) /** @type {HTMLButtonElement} */ (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?.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 = globalThis.getSelection();\n this._savedRange = (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 const 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 (_) { void _; }\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 ? this._lastX : x;\n const ry = y === undefined ? this._lastY : y;\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 > globalThis.innerWidth - 8) left = globalThis.innerWidth - w - 8;\n if (left < 8) left = 8;\n if (top + h > globalThis.innerHeight - 8) top = globalThis.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 = globalThis.getComputedStyle(/** @type {Element} */ (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?.editable;\n if (!editable || !this._savedRange) return;\n editable.focus();\n const sel = globalThis.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?.editable;\n let node = range.startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || !editable?.contains(node)) return;\n\n // Walk up to collect explicitly-set inline properties from the nearest styled ancestor\n const cs = globalThis.getComputedStyle(/** @type {Element} */ (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: Number.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?.[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?.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 = globalThis.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)) /** @type {HTMLElement} */ (el).dataset.anTmp = 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.remove();\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?.editable;\n if (!editable) return;\n\n editable.focus();\n const sel = globalThis.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)) /** @type {Element} */ (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 } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.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\nconst ICON_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"7\" width=\"20\" height=\"14\" rx=\"2\"/><path d=\"M6 11h.01M10 11h.01M14 11h.01M18 11h.01M6 15h.01M18 15h.01M10 15h4\"/><path d=\"M7 3l5 4 5-4\"/></svg>`;\n\nexport class ShortcutsDialog extends BaseDialog {\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n show() {\n this._open();\n }\n\n // ---------------------------------------------------------------------------\n // Build dialog\n // ---------------------------------------------------------------------------\n\n _buildDialog() {\n const L = this.context.locale.shortcutsDialog;\n const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);\n box.classList.add('an-shortcuts-box');\n\n // Close button pinned to the right of the header row\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n 'aria-label': L.close,\n style: 'margin-left:auto',\n });\n closeBtn.textContent = '×';\n this._closeBtn = closeBtn;\n this._firstInput = closeBtn;\n box.querySelector('.an-dialog-header').appendChild(closeBtn);\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 const d1 = on(closeBtn, 'click', () => this._close());\n this._disposers.push(d1);\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, makeDraggable } from '../core/dom.js';\nimport { BaseDialog } from './BaseDialog.js';\n\nexport class FindReplace extends BaseDialog {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n super(context);\n\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 this._useRegex = false;\n this._wholeWord = 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 this._lastUseRegex = null;\n this._lastWholeWord = null;\n\n this._focusTimer = null;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n destroy() {\n clearTimeout(this._focusTimer);\n this._focusTimer = null;\n this._clearHighlights();\n super.destroy();\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) /** @type {HTMLElement} */ (replaceRow).style.display = isReplace ? '' : 'none';\n if (replaceActions) /** @type {HTMLElement} */ (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 an-fr-box' });\n\n // ---- Header: [icon][title] [×] ----\n const header = createElement('div', { class: 'an-fr-header' });\n const titleGroup = createElement('div', { class: 'an-dialog-title-group' });\n const iconEl = createElement('span', { class: 'an-dialog-icon an-dialog-icon--sm' });\n iconEl.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/></svg>`;\n const title = createElement('h3', { class: 'an-dialog-title' });\n title.textContent = L.findTitle;\n titleGroup.append(iconEl, title);\n const closeBtn = createElement('button', {\n type: 'button',\n class: 'an-icon-close',\n title: L.close,\n 'aria-label': L.close,\n });\n closeBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n this._closeBtn = closeBtn;\n header.append(titleGroup, closeBtn);\n box.appendChild(header);\n\n // ---- Search bar: [input] [Aa] [↑] [↓] counter ----\n const searchBar = createElement('div', { class: 'an-fr-search-bar' });\n const findInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'text',\n class: 'an-input an-fr-input',\n placeholder: L.findPlaceholder,\n 'aria-label': L.searchAriaLabel,\n }));\n this._findInput = findInput;\n\n // Case-sensitive toggle (visual button; hidden checkbox kept for state)\n const caseCheckbox = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'checkbox',\n style: 'display:none',\n 'aria-hidden': 'true',\n }));\n this._caseCheckbox = caseCheckbox;\n const caseBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: 'Case sensitive',\n 'aria-label': 'Case sensitive',\n });\n caseBtn.textContent = 'Aa';\n\n const regexBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: L.useRegex,\n 'aria-label': L.useRegex,\n });\n regexBtn.textContent = '.*';\n\n const wholeWordBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: L.wholeWord,\n 'aria-label': L.wholeWord,\n });\n wholeWordBtn.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\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"7\" width=\"18\" height=\"10\" rx=\"2\"/><line x1=\"7\" y1=\"21\" x2=\"7\" y2=\"17\"/><line x1=\"17\" y1=\"21\" x2=\"17\" y2=\"17\"/></svg>`;\n\n const prevBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: 'Previous (Shift+Enter)',\n 'aria-label': 'Previous',\n });\n prevBtn.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=\"18 15 12 9 6 15\"/></svg>`;\n\n const nextBtn = createElement('button', {\n type: 'button',\n class: 'an-fr-icon-btn',\n title: 'Next (Enter)',\n 'aria-label': 'Next',\n });\n nextBtn.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=\"6 9 12 15 18 9\"/></svg>`;\n\n const counter = createElement('span', { class: 'an-fr-counter' });\n this._counterEl = counter;\n\n searchBar.append(findInput, caseCheckbox, caseBtn, regexBtn, wholeWordBtn, prevBtn, nextBtn, counter);\n box.appendChild(searchBar);\n\n // ---- Replace row: [input] [Replace] [All] (hidden by default) ----\n const replaceRow = createElement('div', { class: 'an-fr-replace-row' });\n replaceRow.style.display = 'none';\n const replaceInput = /** @type {HTMLInputElement} */ (createElement('input', {\n type: 'text',\n class: 'an-input an-fr-input',\n placeholder: L.replacePlaceholder,\n 'aria-label': L.replaceAriaLabel,\n }));\n this._replaceInput = replaceInput;\n const replaceBtn = createElement('button', { type: 'button', class: 'an-btn an-fr-replace-btn' });\n replaceBtn.textContent = L.replaceBtn;\n const replaceAllBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary an-fr-replace-btn' });\n replaceAllBtn.textContent = L.replaceAllBtn;\n replaceRow.append(replaceInput, replaceBtn, replaceAllBtn);\n box.appendChild(replaceRow);\n\n // Compat div — _updateMode toggles this; kept empty so existing logic works\n const replaceActions = createElement('div', { class: 'an-fr-replace-actions' });\n replaceActions.style.display = 'none';\n box.appendChild(replaceActions);\n\n overlay.appendChild(box);\n makeDraggable(header, 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(caseBtn, 'click', () => {\n this._caseSensitive = !this._caseSensitive;\n caseCheckbox.checked = this._caseSensitive;\n caseBtn.classList.toggle('an-fr-icon-btn--active', this._caseSensitive);\n this._onSearch();\n });\n // Hidden checkbox change handler keeps backward-compat with programmatic toggles\n const d5 = on(caseCheckbox, 'change', () => {\n this._caseSensitive = caseCheckbox.checked;\n caseBtn.classList.toggle('an-fr-icon-btn--active', this._caseSensitive);\n this._onSearch();\n });\n const d6 = on(nextBtn, 'click', () => this._next());\n const d7 = on(prevBtn, 'click', () => this._prev());\n const d8 = on(replaceBtn, 'click', () => this._replace());\n const d9 = on(replaceAllBtn, 'click', () => this._replaceAll());\n const d10 = on(findInput, 'keydown', (e) => {\n const ke = /** @type {KeyboardEvent} */ (e);\n if (ke.key === 'Enter') {\n e.preventDefault();\n ke.shiftKey ? this._prev() : this._next();\n }\n });\n const d11 = on(replaceInput, 'keydown', (e) => {\n if (/** @type {KeyboardEvent} */ (e).key === 'Enter') {\n e.preventDefault();\n this._replace();\n }\n });\n const dRegex = on(regexBtn, 'click', () => {\n this._useRegex = !this._useRegex;\n regexBtn.classList.toggle('an-fr-icon-btn--active', this._useRegex);\n this._queryRegex = null; // force recompile\n this._lastQuery = null;\n this._onSearch();\n });\n const dWholeWord = on(wholeWordBtn, 'click', () => {\n this._wholeWord = !this._wholeWord;\n wholeWordBtn.classList.toggle('an-fr-icon-btn--active', this._wholeWord);\n this._queryRegex = null;\n this._lastQuery = null;\n this._onSearch();\n });\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, dRegex, dWholeWord);\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 // 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 void _; // surroundContents fails when the range crosses element boundaries\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 this._currentIndex = 0;\n if (this._matches.length === 0) return;\n\n // Highlight the first (current) match\n if (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, case-sensitivity, regex mode, and whole-word haven't changed\n if (this._lastQuery !== query || this._lastCaseSensitive !== this._caseSensitive || this._lastUseRegex !== this._useRegex || this._lastWholeWord !== this._wholeWord) {\n const flags = this._caseSensitive ? 'g' : 'gi';\n try {\n let pattern = this._useRegex\n ? query\n : query.replace(/[.*+?^${}()|[\\]\\\\]/g, String.raw`\\$&`);\n if (this._wholeWord) pattern = `\\\\b${pattern}\\\\b`;\n this._queryRegex = new RegExp(pattern, flags);\n } catch (_) {\n this._queryRegex = null;\n }\n this._lastQuery = query;\n this._lastCaseSensitive = this._caseSensitive;\n this._lastUseRegex = this._useRegex;\n this._lastWholeWord = this._wholeWord;\n }\n if (!this._queryRegex) return results;\n const re = this._queryRegex;\n\n // Cap results to prevent blocking the main thread on very large documents\n const MAX_RESULTS = 500;\n const walker = document.createTreeWalker(root, 0x4 /* NodeFilter.SHOW_TEXT */);\n let node = walker.nextNode();\n while (node && results.length < MAX_RESULTS) {\n re.lastIndex = 0;\n let m;\n while ((m = re.exec(/** @type {Text} */ (node).textContent)) !== null && results.length < MAX_RESULTS) {\n results.push({ node: /** @type {Text} */ (node), start: m.index, end: m.index + m[0].length });\n }\n node = walker.nextNode();\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?.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?.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 match.mark.remove();\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?.parentNode) return;\n const textNode = document.createTextNode(replacement);\n mark.parentNode.insertBefore(textNode, mark);\n mark.remove();\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 mark.remove();\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 ? this.context.locale.findReplace.noResults : '';\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 if (!ctx) { resolve(null); return; } // GPU memory limit — let _confirm() handle null\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 void _; // canvas tainted — resolve with null\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(globalThis.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 on(h, 'touchstart', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const te = /** @type {TouchEvent} */ (e); this._startHandleDrag({ clientX: te.touches[0].clientX, clientY: te.touches[0].clientY }, id);\n }, { passive: false }),\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 if (/** @type {Element} */ (e.target).classList.contains('an-crop-handle')) return;\n if (e.target !== cropBox && e.target !== grid) return;\n e.preventDefault();\n e.stopPropagation();\n this._startBoxMove(e);\n }),\n on(cropBox, 'touchstart', (e) => {\n if (/** @type {Element} */ (e.target).classList.contains('an-crop-handle')) return;\n if (e.target !== cropBox && e.target !== grid) return;\n e.preventDefault();\n e.stopPropagation();\n const te2 = /** @type {TouchEvent} */ (e); this._startBoxMove({ clientX: te2.touches[0].clientX, clientY: te2.touches[0].clientY });\n }, { passive: false }),\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 = globalThis.innerWidth;\n const vh = globalThis.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 > globalThis.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?.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 this._dragDisposers?.();\n const onTouchMove = (e) => {\n e.preventDefault();\n const te3 = /** @type {TouchEvent} */ (e); onMove(/** @type {MouseEvent} */ (/** @type {unknown} */ ({ clientX: te3.touches[0].clientX, clientY: te3.touches[0].clientY })));\n };\n const cleanup = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', cleanup);\n document.removeEventListener('touchmove', onTouchMove);\n document.removeEventListener('touchend', cleanup);\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n this._dragDisposers = null;\n };\n this._dragDisposers = cleanup;\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', cleanup, { once: true });\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', 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 = /** @type {DOMRect} */ (/** @type {unknown} */ ({ 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 this._showCropError(\n 'Cannot crop this image: the image server does not allow cross-origin access. ' +\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 = /^data:image\\/(jpe?g)/i.exec(img.src) ? '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 * Show a non-blocking inline error banner appended to document.body.\n * Auto-dismisses after 4 seconds.\n * @param {string} msg\n */\n _showCropError(msg) {\n const banner = document.createElement('div');\n banner.setAttribute('role', 'alert');\n banner.style.cssText = [\n 'position:fixed', 'bottom:24px', 'left:50%', 'transform:translateX(-50%)',\n 'z-index:10200', 'max-width:420px', 'width:max-content',\n 'background:#7f1d1d', 'color:#fecaca', 'border:1px solid #b91c1c',\n 'border-radius:8px', 'padding:12px 18px',\n 'font:13px/1.5 system-ui,sans-serif',\n 'box-shadow:0 4px 16px rgba(0,0,0,.4)',\n 'pointer-events:auto',\n ].join(';');\n banner.textContent = msg;\n document.body.appendChild(banner);\n setTimeout(() => { banner.remove(); }, 4000);\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._dragDisposers?.();\n this._dragDisposers = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n [this._scrim, this._cropBox, this._toolbar].forEach((el) => {\n el?.remove();\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 globalThis. 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 void _;\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 (_) { void _; }\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 (_) { void _; }\n this._removeBanner();\n }\n\n _removeBanner() {\n this._banner?.remove();\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 = globalThis.getSelection();\n if (!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 = globalThis.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 = re.exec(text);\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 = globalThis.getSelection();\n if (!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.toggleChecklist');\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 = globalThis.getSelection();\n if (!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 = re.exec(upToCursor);\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 /** @type {ChildNode} */ (node).before(beforeNode, el, afterNode);\n /** @type {ChildNode} */ (node).remove();\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', 'hiliteColor', 'removeFormat', 'inlineCode'.\n * Any name not found in the built-in map is silently ignored.\n */\n\nimport { on } from '../core/dom.js';\n\nconst COLOR_PRESETS = [\n '#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#efefef', '#ffffff',\n '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#9900ff', '#ff00ff',\n '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d0e0e3', '#c9daf8', '#d9d2e9', '#ead1dc',\n];\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 hiliteColor: _svg('<path d=\"M3 21v-4l9-9 4 4-9 9z\"/><path d=\"M12 8l4 4\"/><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\"/>'),\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\n// Color buttons are handled via _openColorPicker; not in _ACTIONS.\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 removeFormat: (ctx) => {\n const editable = ctx.layoutInfo?.editable;\n if (!editable) return;\n editable.focus();\n document.execCommand('removeFormat');\n // Also strip inline style attributes which execCommand('removeFormat') misses\n const sel = globalThis.getSelection();\n if (sel?.rangeCount > 0 && !sel.getRangeAt(0).collapsed) {\n const range = sel.getRangeAt(0);\n const ancestor = range.commonAncestorContainer;\n const root = /** @type {Element|null} */ (ancestor.nodeType === 1 ? ancestor : ancestor.parentElement);\n if (root) {\n const candidates = [root, ...root.querySelectorAll('[style]')];\n for (const el of candidates) {\n if (el.hasAttribute('style') && range.intersectsNode(el)) {\n el.removeAttribute('style');\n }\n }\n }\n }\n ctx.invoke('editor.afterCommand');\n },\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\nconst _COLOR_TYPES = { foreColor: true, hiliteColor: true };\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 /** @type {HTMLElement|null} */\n this._picker = null;\n this._pickerType = null; // 'foreColor' | 'hiliteColor'\n this._savedRange = 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 this._buildColorPicker();\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 const d7 = on(globalThis, 'scroll', () => this._hide(), { passive: true });\n const d8 = on(globalThis, 'resize', () => this._hide(), { passive: true });\n this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8);\n return this;\n }\n\n destroy() {\n this._el?.remove();\n this._el = null;\n this._picker?.remove();\n this._picker = 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', 'hiliteColor', 'removeFormat'];\n for (const name of items) {\n if (!_ICONS[name]) continue;\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.dataset.name = name;\n btn.setAttribute('aria-label', name);\n\n if (_COLOR_TYPES[name]) {\n // Color button: SVG icon stacked above a colored strip, matching ContextMenu style\n btn.className = 'an-bubble-btn an-bubble-btn--color';\n const iconWrap = document.createElement('span');\n iconWrap.className = 'an-bubble-btn-svg';\n iconWrap.innerHTML = _ICONS[name];\n const strip = document.createElement('span');\n strip.className = 'an-bubble-color-strip';\n strip.style.background = name === 'foreColor' ? '#000000' : 'transparent';\n btn.appendChild(iconWrap);\n btn.appendChild(strip);\n } else {\n btn.className = 'an-bubble-btn';\n btn.innerHTML = _ICONS[name];\n }\n\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\n // Color buttons: save selection and open the picker\n if (_COLOR_TYPES[name]) {\n this._openColorPicker(name, btn);\n return;\n }\n\n this.context.invoke('editor.focus');\n if (_ACTIONS[name]) _ACTIONS[name](this.context);\n this._syncActive();\n });\n el.appendChild(btn);\n }\n\n document.body.appendChild(el);\n this._el = el;\n // Cache button references once — avoids querySelectorAll on every selectionchange\n this._btnCache = Array.from(el.querySelectorAll('.an-bubble-btn'));\n }\n\n _buildColorPicker() {\n const picker = document.createElement('div');\n picker.className = 'an-bubble-color-picker';\n picker.style.display = 'none';\n\n // Prevent any mousedown inside the picker from collapsing the editor selection\n picker.addEventListener('mousedown', (e) => e.preventDefault());\n\n const palette = document.createElement('div');\n palette.className = 'an-context-color-palette';\n\n COLOR_PRESETS.forEach((color) => {\n const sw = document.createElement('div');\n sw.className = 'an-context-color-swatch';\n sw.title = color;\n sw.style.background = color;\n sw.setAttribute('role', 'button');\n sw.setAttribute('aria-label', color);\n sw.addEventListener('click', (e) => {\n e.stopPropagation();\n this._applyColor(this._pickerType, color);\n });\n palette.appendChild(sw);\n });\n\n // \"No highlight\" swatch — only shown for hiliteColor\n const noColorBtn = document.createElement('div');\n noColorBtn.className = 'an-context-color-swatch an-context-color-none';\n noColorBtn.title = 'No highlight';\n noColorBtn.setAttribute('role', 'button');\n noColorBtn.setAttribute('aria-label', 'No highlight');\n noColorBtn.innerHTML = `<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 noColorBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this._applyColor('hiliteColor', 'transparent');\n });\n\n // Custom color input row\n const customRow = document.createElement('div');\n customRow.className = 'an-context-color-custom';\n const colorInput = document.createElement('input');\n colorInput.type = 'color';\n colorInput.value = '#000000';\n colorInput.title = 'Custom color';\n // stopPropagation so the picker's mousedown-preventDefault doesn't block the native color dialog\n colorInput.addEventListener('mousedown', (e) => e.stopPropagation());\n colorInput.addEventListener('change', () => {\n this._applyColor(this._pickerType, colorInput.value);\n });\n const customLabel = document.createElement('span');\n customLabel.textContent = 'Custom…';\n customRow.appendChild(colorInput);\n customRow.appendChild(customLabel);\n\n picker.appendChild(palette);\n picker.appendChild(customRow);\n document.body.appendChild(picker);\n\n this._picker = picker;\n const pickerAny = /** @type {any} */ (picker);\n pickerAny._paletteEl = palette;\n pickerAny._noColorBtn = noColorBtn;\n pickerAny._colorInput = colorInput;\n }\n\n _openColorPicker(type, anchorBtn) {\n // Save current selection before the picker might shift focus\n const sel = globalThis.getSelection();\n if (sel?.rangeCount > 0) {\n this._savedRange = sel.getRangeAt(0).cloneRange();\n }\n\n this._pickerType = type;\n\n // Toggle \"No highlight\" swatch based on type\n const pickerAny = /** @type {any} */ (this._picker);\n const palette = pickerAny._paletteEl;\n const noColorBtn = pickerAny._noColorBtn;\n if (type === 'hiliteColor') {\n if (!palette.contains(noColorBtn)) palette.appendChild(noColorBtn);\n } else if (palette.contains(noColorBtn)) {\n noColorBtn.remove();\n }\n\n // Seed the custom color input\n /** @type {any} */ (this._picker)._colorInput.value = type === 'foreColor' ? '#000000' : '#ffff00';\n\n // Position the picker above the bubble toolbar (not blocking the content below it).\n // Fall back to below the toolbar if there's not enough room above.\n this._picker.style.display = 'block';\n const pw = this._picker.offsetWidth;\n const ph = this._picker.offsetHeight;\n const toolbarRect = this._el.getBoundingClientRect();\n\n let top = toolbarRect.top - ph - 6;\n if (top < 8) top = toolbarRect.bottom + 6;\n\n // Align horizontally with the clicked button, clamped to viewport\n const btnRect = anchorBtn.getBoundingClientRect();\n let left = btnRect.left;\n left = Math.max(8, Math.min(left, globalThis.innerWidth - pw - 8));\n\n this._picker.style.left = `${left}px`;\n this._picker.style.top = `${top}px`;\n }\n\n _closeColorPicker() {\n if (this._picker) this._picker.style.display = 'none';\n this._pickerType = null;\n }\n\n /** Restore the saved selection, apply execCommand, update the color strip, then close the picker. */\n _applyColor(type, color) {\n const editable = this.context.layoutInfo?.editable;\n if (!editable || !this._savedRange) return;\n\n editable.focus();\n const sel = globalThis.getSelection();\n sel.removeAllRanges();\n try { sel.addRange(this._savedRange.cloneRange()); } catch (_) { void _; return; }\n\n // Firefox does not support 'hiliteColor'; fall back to 'backColor'\n const cmd = type === 'hiliteColor' ? 'hiliteColor' : type;\n if (!document.execCommand(cmd, false, color) && cmd === 'hiliteColor') {\n document.execCommand('backColor', false, color);\n }\n this.context.invoke('editor.afterCommand');\n\n // Update the color strip on the corresponding button\n const name = type === 'hiliteColor' ? 'hiliteColor' : 'foreColor';\n const btn = this._el?.querySelector(`[data-name=\"${name}\"]`);\n const strip = btn?.querySelector('.an-bubble-color-strip');\n if (strip) /** @type {HTMLElement} */ (strip).style.background = color === 'transparent' ? 'transparent' : color;\n\n this._closeColorPicker();\n this._syncActive();\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, globalThis.innerWidth - bw - 8));\n\n if (top < 8) {\n top = rect.bottom + gap;\n }\n\n // If the Table Tooltip is visible, avoid overlapping it by flipping below the selection.\n // The Table Tooltip sits above the table, which is the same vertical zone the bubble\n // toolbar would normally occupy when text is selected inside a table cell.\n const tableTooltipEl = document.querySelector('.an-table-tooltip');\n if (tableTooltipEl && /** @type {HTMLElement} */ (tableTooltipEl).style.display !== 'none') {\n const ttRect = tableTooltipEl.getBoundingClientRect();\n const overlapsVertically = top < ttRect.bottom + gap && top + bh > ttRect.top - gap;\n if (overlapsVertically) {\n top = rect.bottom + gap;\n if (top + bh > globalThis.innerHeight - 8) top = ttRect.bottom + gap;\n }\n }\n\n el.style.top = `${top}px`;\n el.style.left = `${left}px`;\n el.style.visibility = '';\n\n this._syncActive();\n this._syncColorStrips();\n this._visible = true;\n }\n\n _hide() {\n if (!this._el) return;\n this._el.style.display = 'none';\n this._visible = false;\n this._closeColorPicker();\n }\n\n _syncActive() {\n if (!this._btnCache) return;\n this._btnCache.forEach((btn) => {\n const activeFn = _ACTIVE[/** @type {HTMLElement} */ (btn).dataset.name];\n btn.classList.toggle('an-active', !!(activeFn?.()));\n });\n }\n\n /** Read the current selection's color and update the color-strip indicators. */\n _syncColorStrips() {\n if (!this._el) return;\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return;\n let node = sel.getRangeAt(0).startContainer;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node) return;\n const cs = globalThis.getComputedStyle(/** @type {Element} */ (node));\n\n const foreBtn = this._el.querySelector('[data-name=\"foreColor\"]');\n const foreStrip = foreBtn?.querySelector('.an-bubble-color-strip');\n if (foreStrip) /** @type {HTMLElement} */ (foreStrip).style.background = cs.color || '#000000';\n\n const hiliteBtn = this._el.querySelector('[data-name=\"hiliteColor\"]');\n const hiliteStrip = hiliteBtn?.querySelector('.an-bubble-color-strip');\n if (hiliteStrip) {\n const bg = cs.backgroundColor;\n /** @type {HTMLElement} */ (hiliteStrip).style.background = (!bg || bg === 'rgba(0, 0, 0, 0)' || bg === 'transparent') ? 'transparent' : bg;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n _onSelectionChange() {\n cancelAnimationFrame(this._rafId);\n this._rafId = requestAnimationFrame(() => {\n if (this._contextMenuOpen) return;\n // Keep toolbar visible while color picker is open\n if (this._picker && this._picker.style.display !== 'none') return;\n\n const sel = globalThis.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 in read-only mode\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, the bubble toolbar, and the color picker\n if (!this._visible) return;\n if (this._el?.contains(e.target)) return;\n if (this._picker?.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') {\n if (this._picker && this._picker.style.display !== 'none') {\n this._closeColorPicker();\n } else if (this._visible) {\n this._hide();\n }\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 * onError: (err: Error) => void,\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 onError: cfg.onError || 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 this._dropdown?.remove();\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\n // Event delegation: single listeners on the container instead of per-item\n el.addEventListener('mousedown', (e) => e.preventDefault());\n el.addEventListener('click', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-mention-item'));\n if (item) this._select(+item.dataset.index);\n });\n el.addEventListener('mousemove', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-mention-item'));\n if (item) this._highlightItem(+item.dataset.index);\n });\n\n document.body.appendChild(el);\n this._dropdown = el;\n }\n\n _renderItems(items) {\n const dd = this._dropdown;\n this._items = items.slice(0, this._cfg.maxResults);\n this._activeIndex = this._items.length > 0 ? 0 : -1;\n\n // Build all items in a DocumentFragment — one batch DOM insertion\n const frag = document.createDocumentFragment();\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 = String(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 frag.appendChild(li);\n });\n\n dd.innerHTML = ''; // one clear\n dd.appendChild(frag); // one batch insert\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 > globalThis.innerHeight) {\n top = rect.top - ddh - 4;\n }\n left = Math.max(8, Math.min(left, globalThis.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?.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 (_) { void _; }\n }\n\n // Fallback: use getClientRects() on the current collapsed selection\n const sel = globalThis.getSelection();\n if (!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 = globalThis.getSelection();\n if (!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 const cb = (items) => {\n if (!Array.isArray(items) || items.length === 0) {\n this._hideDropdown();\n return;\n }\n this._renderItems(items);\n this._showDropdown();\n };\n let result;\n try {\n result = this._cfg.onSearch(this._query, cb);\n } catch (err) {\n this._hideDropdown();\n if (typeof this._cfg.onError === 'function') this._cfg.onError(err);\n return;\n }\n if (result && typeof result.then === 'function') {\n result.then(cb).catch((err) => {\n this._hideDropdown();\n if (typeof this._cfg.onError === 'function') this._cfg.onError(err);\n });\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?.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 = globalThis.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 + '&#8203;');\n this._hideDropdown();\n this.context.triggerEvent('change', this.context.getHTML());\n }\n}\n","/**\n * SlashMenu.js — Notion-style \"/\" command palette for quick block insertion.\n *\n * Typing \"/\" as the very first character of an otherwise-empty block opens a\n * filterable list of quick-insert commands (headings, lists, table, image, …).\n * Arrow keys navigate, Enter/Tab selects, Escape or deleting back past the\n * \"/\" closes it. Disabled via `slashMenu: false`.\n *\n * Positioning follows the same synchronous-caret-rect technique as Mention.js:\n * getBoundingClientRect() on a zero-width Range over the trigger character is\n * reliable while the triggering DOM event is still live, but often returns an\n * empty rect once deferred into a callback — so the rect is captured eagerly\n * in `_onInput`, not lazily when the menu is rendered.\n */\n\nimport { on } from '../core/dom.js';\n\nexport class SlashMenu {\n /** @param {import('../Context.js').Context} context */\n constructor(context) {\n this.context = context;\n this.options = context.options;\n this._disposers = [];\n\n /** @type {HTMLElement|null} */\n this._menu = null;\n /** @type {Array<{id: string, label: string, keywords: string, run: () => void}>} */\n this._filtered = [];\n this._activeIndex = -1;\n this._open = false;\n this._query = '';\n /** @type {Text|null} */\n this._textNode = null;\n this._triggerOffset = 0;\n /** @type {DOMRect|null} */\n this._caretRect = null;\n }\n\n initialize() {\n if (this.options.slashMenu === false) return this;\n const editable = this.context.layoutInfo.editable;\n const d1 = on(editable, 'input', () => this._onInput());\n const d2 = on(editable, 'keydown', (e) => this._onKeydown(e));\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 this._menu?.remove();\n this._menu = null;\n this._disposers.forEach((d) => d());\n this._disposers = [];\n }\n\n // ---------------------------------------------------------------------------\n // Command list\n // ---------------------------------------------------------------------------\n\n _commands() {\n const L = this.context.locale.slashMenu;\n const ctx = this.context;\n const builtIns = [\n { id: 'h1', label: L.heading1, keywords: 'h1 heading title', run: () => ctx.invoke('editor.formatBlock', 'h1') },\n { id: 'h2', label: L.heading2, keywords: 'h2 heading subtitle', run: () => ctx.invoke('editor.formatBlock', 'h2') },\n { id: 'h3', label: L.heading3, keywords: 'h3 heading', run: () => ctx.invoke('editor.formatBlock', 'h3') },\n { id: 'ul', label: L.bulletList, keywords: 'ul bullet list unordered', run: () => ctx.invoke('editor.insertUL') },\n { id: 'ol', label: L.numberedList, keywords: 'ol numbered list ordered', run: () => ctx.invoke('editor.insertOL') },\n { id: 'checklist', label: L.checklist, keywords: 'checklist todo checkbox task', run: () => ctx.invoke('editor.toggleChecklist') },\n { id: 'quote', label: L.blockquote, keywords: 'quote blockquote', run: () => ctx.invoke('editor.formatBlock', 'blockquote') },\n { id: 'code', label: L.codeBlock, keywords: 'code pre block', run: () => ctx.invoke('editor.formatBlock', 'pre') },\n { id: 'hr', label: L.horizontalRule, keywords: 'hr divider rule line', run: () => ctx.invoke('editor.insertHr') },\n { id: 'table', label: L.table, keywords: 'table grid', run: () => ctx.invoke('editor.insertTable', 3, 3) },\n { id: 'image', label: L.image, keywords: 'image picture photo upload', run: () => ctx.invoke('imageDialog.show') },\n ];\n const custom = (this.options.slashCommands || []).map((command) => ({\n id: command.id,\n label: command.label || command.id,\n keywords: command.keywords || '',\n run: () => command.run(ctx),\n }));\n return [...builtIns, ...custom];\n }\n\n refresh() {\n if (this._open) this._filterAndRender();\n }\n\n // ---------------------------------------------------------------------------\n // Menu DOM\n // ---------------------------------------------------------------------------\n\n _buildMenu() {\n const el = document.createElement('div');\n el.className = 'an-slash-menu';\n el.setAttribute('role', 'listbox');\n el.style.display = 'none';\n\n el.addEventListener('mousedown', (e) => e.preventDefault());\n el.addEventListener('click', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-slash-menu-item'));\n if (item) this._select(+item.dataset.index);\n });\n el.addEventListener('mousemove', (e) => {\n const item = /** @type {HTMLElement} */ (/** @type {Element} */ (e.target)?.closest('.an-slash-menu-item'));\n if (item) this._highlight(+item.dataset.index);\n });\n\n document.body.appendChild(el);\n this._menu = el;\n return el;\n }\n\n _renderItems() {\n if (!this._menu) this._buildMenu();\n const menu = this._menu;\n const L = this.context.locale.slashMenu;\n\n if (this._filtered.length === 0) {\n menu.innerHTML = '';\n const empty = document.createElement('div');\n empty.className = 'an-slash-menu-empty';\n empty.textContent = L.noResults;\n menu.appendChild(empty);\n this._activeIndex = -1;\n return;\n }\n\n const frag = document.createDocumentFragment();\n this._filtered.forEach((item, i) => {\n const row = document.createElement('div');\n row.className = 'an-slash-menu-item';\n row.setAttribute('role', 'option');\n row.id = `an-slash-option-${item.id}`;\n row.dataset.index = String(i);\n row.textContent = item.label;\n frag.appendChild(row);\n });\n menu.innerHTML = '';\n menu.appendChild(frag);\n this._highlight(0);\n }\n\n _highlight(index) {\n if (!this._menu) return;\n this._menu.querySelectorAll('.an-slash-menu-item').forEach((el, i) => {\n const active = i === index;\n el.classList.toggle('an-slash-menu-active', active);\n el.setAttribute('aria-selected', String(active));\n if (active) this._menu.setAttribute('aria-activedescendant', el.id);\n });\n this._activeIndex = index;\n }\n\n _position() {\n const menu = this._menu;\n const rect = this._caretRect;\n if (!menu || !rect || rect.height === 0) return;\n\n menu.style.visibility = 'hidden';\n menu.style.display = 'block';\n const mh = menu.offsetHeight;\n const mw = menu.offsetWidth;\n\n let top = rect.bottom + 4;\n let left = rect.left;\n if (rect.bottom + mh + 8 > globalThis.innerHeight) {\n top = rect.top - mh - 4;\n }\n left = Math.max(8, Math.min(left, globalThis.innerWidth - mw - 8));\n\n menu.style.top = `${top}px`;\n menu.style.left = `${left}px`;\n menu.style.visibility = '';\n }\n\n _open_() {\n this._open = true;\n this._filterAndRender();\n this._position();\n }\n\n _close() {\n if (this._menu) this._menu.style.display = 'none';\n this._open = false;\n this._filtered = [];\n this._activeIndex = -1;\n this._menu?.removeAttribute('aria-activedescendant');\n this._textNode = null;\n this._caretRect = null;\n this._query = '';\n }\n\n // ---------------------------------------------------------------------------\n // Trigger detection\n // ---------------------------------------------------------------------------\n\n _isBlock(node) {\n if (node.nodeType !== Node.ELEMENT_NODE) return false;\n const display = globalThis.getComputedStyle(node).display;\n return display === 'block' || display === 'list-item' || display === 'table-cell';\n }\n\n /**\n * Detects a \"/\" trigger at the caret, requiring it to be the only content\n * typed so far in its block (i.e. the block's text is exactly \"/\" + query,\n * nothing before or after). This deliberately avoids firing mid-sentence\n * (e.g. \"10/20\", \"and/or\").\n * @returns {{ query: string, textNode: Text, triggerOffset: number } | null}\n */\n _getTriggerContext() {\n const sel = globalThis.getSelection();\n if (!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 if (range.startContainer.nodeType !== Node.TEXT_NODE) return null;\n\n let block = range.startContainer.parentNode;\n while (block && block !== editable && !this._isBlock(block)) block = block.parentNode;\n if (!block || block === editable) return null;\n\n const fullText = block.textContent || '';\n const beforeRange = document.createRange();\n beforeRange.setStart(block, 0);\n beforeRange.setEnd(range.startContainer, range.startOffset);\n const before = beforeRange.toString();\n\n const m = /^\\/(\\S*)$/.exec(before);\n if (!m) return null;\n if (fullText.length > before.length) return null; // content after the caret\n\n return {\n query: m[1],\n textNode: /** @type {Text} */ (range.startContainer),\n triggerOffset: range.startOffset - m[0].length,\n };\n }\n\n /**\n * Captures the caret rect synchronously — see file header for why this\n * can't be deferred to a later tick.\n */\n _captureCaretRect(textNode, triggerOffset) {\n try {\n const r = document.createRange();\n const end = Math.min(triggerOffset + 1, textNode.textContent.length);\n r.setStart(textNode, triggerOffset);\n r.setEnd(textNode, end);\n const candidate = r.getBoundingClientRect();\n if (candidate.height > 0) return candidate;\n } catch (_) { void _; }\n\n const sel = globalThis.getSelection();\n if (!sel?.rangeCount) return null;\n const rects = sel.getRangeAt(0).getClientRects();\n return rects.length > 0 ? rects[rects.length - 1] : null;\n }\n\n _filterAndRender() {\n const q = this._query.toLowerCase();\n this._filtered = q\n ? this._commands().filter((c) => c.keywords.includes(q) || c.label.toLowerCase().includes(q))\n : this._commands();\n this._renderItems();\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n _onInput() {\n const ctx = this._getTriggerContext();\n if (!ctx) {\n if (this._open) this._close();\n return;\n }\n\n this._textNode = ctx.textNode;\n this._triggerOffset = ctx.triggerOffset;\n this._query = ctx.query;\n this._caretRect = this._captureCaretRect(ctx.textNode, ctx.triggerOffset);\n\n if (!this._open) this._open_();\n else { this._filterAndRender(); this._position(); }\n }\n\n _onKeydown(e) {\n if (!this._open) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (this._filtered.length === 0) return;\n this._highlight((this._activeIndex + 1) % this._filtered.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (this._filtered.length === 0) return;\n this._highlight((this._activeIndex - 1 + this._filtered.length) % this._filtered.length);\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 e.preventDefault();\n this._close();\n }\n }\n\n _onDocClick(e) {\n if (!this._open) return;\n if (this._menu?.contains(e.target)) return;\n this._close();\n }\n\n // ---------------------------------------------------------------------------\n // Selection\n // ---------------------------------------------------------------------------\n\n _deleteTriggerText() {\n const node = this._textNode;\n if (!node?.isConnected) return;\n const before = node.textContent.slice(0, this._triggerOffset);\n const after = node.textContent.slice(this._triggerOffset + 1 + this._query.length);\n node.textContent = before + after;\n\n const sel = globalThis.getSelection();\n if (!sel) return;\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 _makeTriggerRemover() {\n const node = this._textNode;\n const triggerOffset = this._triggerOffset;\n const query = this._query;\n return () => {\n if (!node?.isConnected) return;\n const before = node.textContent.slice(0, triggerOffset);\n const after = node.textContent.slice(triggerOffset + 1 + query.length);\n node.textContent = before + after;\n\n const sel = globalThis.getSelection();\n if (!sel) return;\n const range = document.createRange();\n range.setStart(node, triggerOffset);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n };\n }\n\n _select(index) {\n const item = this._filtered[index];\n if (!item) return;\n\n if (item.id === 'image') {\n const beforeInsert = this._makeTriggerRemover();\n this._close();\n this.context.invoke('imageDialog.show', { beforeInsert });\n return;\n }\n\n this._deleteTriggerText();\n this._close();\n // Editor.* methods invoked by commands already call afterCommand()\n // internally (toolbar/statusbar refresh + debounced undo snapshot + the\n // 'change' event), so no manual triggerEvent here — see Editor.js.\n item.run();\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 { registerButton } from './module/Buttons.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';\nimport { SlashMenu } from './module/SlashMenu.js';\n\n/** Module registry shared across all Context instances (populated via AutumnNote.registerModule). */\nexport const _customModules = new Map();\n\n/**\n * Modules whose registration depends on an option value. Declared once so the\n * initial mount (`_registerModules`) and runtime toggles (`updateOptions`) can\n * never drift apart — previously `updateOptions({ bubbleToolbar: true })`\n * changed the option but silently left the module unregistered.\n * @type {Array<{ name: string, Class: new (ctx: Context) => { initialize: () => any, destroy?: () => void }, enabled: (options: any) => boolean }>}\n */\nconst OPTIONAL_MODULES = [\n { name: 'autoSaveRestore', Class: AutoSaveRestore, enabled: (o) => !!o.autoSaveRestore },\n { name: 'markdownShortcuts', Class: MarkdownShortcuts, enabled: (o) => o.markdownShortcuts !== false },\n { name: 'bubbleToolbar', Class: BubbleToolbar, enabled: (o) => !!o.bubbleToolbar },\n { name: 'mention', Class: Mention, enabled: (o) => !!o.mention },\n { name: 'slashMenu', Class: SlashMenu, enabled: (o) => o.slashMenu !== false },\n];\n\n/** Global plugin registry (populated via AutumnNote.use()). Applied to every new Context. */\nexport const _globalPlugins = 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 = /** @type {any} */ ({});\n\n /** @type {Map<string, Function[]>} */\n this._listeners = new Map();\n\n /** @type {Map<string, object>} */\n this._modules = new Map();\n\n /** @type {Map<string, { plugin: object, publicApi: * }>} */\n this._plugins = new Map();\n\n this._disposers = [];\n this._alive = false;\n this._autoSaveTimer = null;\n this._pendingAutoSave = null;\n this._suppressedRemoteHTML = null;\n /** @type {Promise<void>|null} Settles when destroy()'s closing auto-save finishes */\n this._destroyPromise = null;\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?.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?.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 // Apply plugins registered globally via AutumnNote.use()\n this._applyGlobalPlugins();\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 for (const { name, Class, enabled } of OPTIONAL_MODULES) {\n if (enabled(this.options)) register(name, Class);\n }\n\n // Custom modules registered via AutumnNote.registerModule()\n if (_customModules.size > 0) {\n for (const [name, ModuleClass] of _customModules) {\n register(name, ModuleClass);\n }\n }\n }\n\n /**\n * Registers or tears down option-gated modules so they match the current\n * option values. Called after `updateOptions()` so toggling e.g.\n * `bubbleToolbar` at runtime actually takes effect.\n */\n _syncOptionalModules() {\n for (const { name, Class, enabled } of OPTIONAL_MODULES) {\n const shouldRun = enabled(this.options);\n const isRunning = this._modules.has(name);\n if (shouldRun === isRunning) continue;\n\n if (shouldRun) {\n const instance = new Class(this);\n this._modules.set(name, instance);\n instance.initialize();\n } else {\n const instance = this._modules.get(name);\n if (typeof instance?.destroy === 'function') instance.destroy();\n this._modules.delete(name);\n }\n }\n }\n\n /**\n * Registers and initialises a custom module on this instance.\n * @param {string} name\n * @param {new (ctx: this) => any} 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 registerSlashCommand(command) {\n if (!command?.id || typeof command.run !== 'function') {\n throw new TypeError('[AutumnNote] Slash command requires an id and run(context) function.');\n }\n const commands = this.options.slashCommands || (this.options.slashCommands = []);\n const index = commands.findIndex((item) => item.id === command.id);\n if (index >= 0) commands[index] = command;\n else commands.push(command);\n this.invoke('slashMenu.refresh');\n return this;\n }\n\n /**\n * Installs a plugin on this editor instance.\n * If called after create(), buttons are registered immediately but the toolbar\n * must be rebuilt via ctx.invoke('toolbar.rebuild') to render new buttons.\n * @param {object} plugin - { name, version?, buttons?, install?, uninstall? }\n * @param {object} [options] - Forwarded to plugin.install(context, options)\n * @returns {this}\n */\n use(plugin, options = {}) {\n if (Array.isArray(plugin.buttons)) {\n plugin.buttons.forEach((b) => registerButton(b));\n }\n this._installPlugin(plugin, options);\n return this;\n }\n\n /**\n * Returns the public API returned by plugin.install(), or null.\n * @param {string} name\n * @returns {*}\n */\n getPlugin(name) {\n return this._plugins.get(name)?.publicApi ?? null;\n }\n\n _installPlugin(plugin, pluginOptions = {}) {\n const { name } = plugin;\n if (!name || typeof name !== 'string') {\n console.warn('[AutumnNote] Plugin must have a string `name` property.');\n return;\n }\n if (this._plugins.has(name)) {\n console.warn(`[AutumnNote] Plugin \"${name}\" already installed on this instance. Skipping.`);\n return;\n }\n const publicApi = (typeof plugin.install === 'function')\n ? plugin.install(this, pluginOptions) ?? null\n : null;\n this._plugins.set(name, { plugin, publicApi });\n }\n\n _applyGlobalPlugins() {\n if (_globalPlugins.size === 0) return;\n for (const { plugin, options } of _globalPlugins.values()) {\n this._installPlugin(plugin, options);\n }\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', (html) => this._syncToTarget(html));\n const dRemote = this.on('change', (html) => {\n if (this.options.blockIds) { this.ensureBlockIds(); html = this.getHTML(); }\n if (html === this._suppressedRemoteHTML) { this._suppressedRemoteHTML = null; return; }\n this.options.collaborationAdapter?.onLocalChange?.(html, this);\n });\n this._disposers.push(d0, d1, d2, d3, dRemote);\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', (html) => this._scheduleAutoSave(html));\n this._disposers.push(d4);\n }\n }\n\n _scheduleAutoSave(html) {\n this._pendingAutoSave = html;\n clearTimeout(this._autoSaveTimer);\n this._autoSaveTimer = setTimeout(() => this.flushAutoSave(), this.options.autoSaveDelay ?? 400);\n }\n\n async flushAutoSave() {\n clearTimeout(this._autoSaveTimer);\n this._autoSaveTimer = null;\n if (this._pendingAutoSave == null) return;\n const html = this._pendingAutoSave;\n this._pendingAutoSave = null;\n const key = this.options.autoSaveKey;\n const savedAt = Date.now();\n try {\n const adapter = this.options.autoSaveAdapter;\n if (typeof adapter?.save === 'function') {\n await adapter.save({ key, html, savedAt, context: this });\n } else {\n localStorage.setItem(key, html);\n localStorage.setItem(key + ':asrmeta', JSON.stringify({ savedAt }));\n }\n this.triggerEvent('autoSave', { key, html, savedAt });\n } catch (error) {\n this.triggerEvent('autoSaveError', { key, error });\n }\n }\n\n async loadAutoSave() {\n const adapter = this.options.autoSaveAdapter;\n if (typeof adapter?.load === 'function') {\n return adapter.load({ key: this.options.autoSaveKey, context: this });\n }\n try { return localStorage.getItem(this.options.autoSaveKey); } catch (_) { return null; }\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 /** Updates runtime-safe options without recreating the editor. */\n updateOptions(overrides = {}) {\n const next = mergeDeep(this.options, overrides);\n Object.keys(this.options).forEach((key) => delete this.options[key]);\n Object.assign(this.options, next);\n\n const { container, editable } = this.layoutInfo;\n if (Object.hasOwn(overrides, 'readOnly')) this.setDisabled(Boolean(this.options.readOnly));\n if (Object.hasOwn(overrides, 'spellcheck')) editable.spellcheck = this.options.spellcheck !== false;\n if (Object.hasOwn(overrides, 'placeholder')) editable.dataset.placeholder = this.options.placeholder || '';\n if (Object.hasOwn(overrides, 'direction')) {\n const rtl = this.options.direction === 'rtl';\n editable.setAttribute('dir', rtl ? 'rtl' : 'ltr');\n container.classList.toggle('an-dir-rtl', rtl);\n }\n if (Object.hasOwn(overrides, 'height') || Object.hasOwn(overrides, 'minHeight')) {\n const height = this.options.height || this.options.minHeight || 0;\n editable.style.minHeight = height ? `${height}px` : '';\n }\n if (Object.hasOwn(overrides, 'maxHeight')) {\n editable.style.maxHeight = this.options.maxHeight ? `${this.options.maxHeight}px` : '';\n }\n if (Object.hasOwn(overrides, 'toolbar')) this.invoke('toolbar.rebuild');\n // Start/stop option-gated modules (bubbleToolbar, mention, slashMenu, ...)\n // so toggling them here behaves the same as passing them to create().\n this._syncOptionalModules();\n this.invoke('statusbar.update');\n this.triggerEvent('optionsChange', { ...overrides });\n return this;\n }\n\n /**\n * Returns the current HTML content of the editor.\n * Zero-width spaces (U+200B) inserted by inline editing helpers are stripped\n * from the output so they don't leak into the consumer's HTML.\n * @returns {string}\n */\n getHTML() {\n const html = this.invoke('editor.getHTML');\n return typeof html === 'string' ? html.replace(/​/g, '') : html;\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 the number of available undo steps.\n * @returns {number}\n */\n getUndoCount() {\n return this.invoke('editor.getUndoCount') ?? 0;\n }\n\n /**\n * Returns the number of available redo steps.\n * @returns {number}\n */\n getRedoCount() {\n return this.invoke('editor.getRedoCount') ?? 0;\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 getSelectionBookmark() {\n return this.invoke('editor.getSelectionBookmark') ?? null;\n }\n\n restoreSelectionBookmark(bookmark) {\n return this.invoke('editor.restoreSelectionBookmark', bookmark);\n }\n\n async importDocument(format, data) {\n const adapter = this.options.documentAdapters?.[format];\n let html;\n if (typeof adapter?.import === 'function') html = await adapter.import(data, this);\n else if (format === 'html') html = String(data ?? '');\n else if (format === 'markdown') { this.setMarkdown(String(data ?? '')); return this; }\n else if (format === 'text') { this.setText(String(data ?? '')); return this; }\n else throw new Error(`[AutumnNote] No importer registered for \"${format}\".`);\n this.setHTML(html);\n return this;\n }\n\n async exportDocument(format) {\n const adapter = this.options.documentAdapters?.[format];\n if (typeof adapter?.export === 'function') return adapter.export(this, this.getHTML());\n if (format === 'html') return this.getHTML();\n if (format === 'markdown') return this.getMarkdown();\n if (format === 'text') return this.getText();\n throw new Error(`[AutumnNote] No exporter registered for \"${format}\".`);\n }\n\n ensureBlockIds() {\n const blocks = this.layoutInfo.editable.children;\n for (const block of blocks) {\n if (!block.hasAttribute('data-an-block-id')) {\n const id = globalThis.crypto?.randomUUID?.() || `an-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n block.setAttribute('data-an-block-id', id);\n }\n }\n return this;\n }\n\n getDocument() {\n if (this.options.blockIds) this.ensureBlockIds();\n return { version: 1, html: this.getHTML(), markdown: this.getMarkdown() };\n }\n\n loadDocument(documentData) {\n this.setHTML(documentData?.html || '');\n this.clearHistory();\n return this;\n }\n\n applyRemoteHTML(html) {\n this.setHTML(html);\n this._suppressedRemoteHTML = this.getHTML();\n this.clearHistory();\n return this;\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 a.remove();\n URL.revokeObjectURL(url);\n }\n\n /**\n * Opens the editor content in a new globalThis 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, (c) => `&#${c.charCodeAt(0)};`);\n const markup = '<!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 const blob = new Blob([markup], { type: 'text/html' });\n const url = URL.createObjectURL(blob);\n const w = globalThis.open(url, '_blank');\n if (!w) { URL.revokeObjectURL(url); return; } // popup blocked by browser\n w.addEventListener('load', () => {\n w.print();\n URL.revokeObjectURL(url);\n });\n }\n\n /**\n * Returns an array of heading objects representing the table of contents.\n * Each entry has: level (1-6), text (heading text), element (DOM element).\n * @returns {{ level: number, text: string, element: HTMLElement }[]}\n */\n getTableOfContents() {\n const headings = Array.from(\n this.layoutInfo.editable.querySelectorAll('h1,h2,h3,h4,h5,h6')\n );\n return headings.map((el) => ({\n level: parseInt(el.tagName[1], 10),\n text: el.textContent?.trim() ?? '',\n element: /** @type {HTMLElement} */ (el),\n }));\n }\n\n /**\n * Moves focus into the editable area.\n */\n focus() {\n this.layoutInfo.editable.focus();\n }\n\n /**\n * Removes focus from the editable area.\n */\n blur() {\n this.layoutInfo.editable.blur();\n }\n\n /**\n * Returns true when the editor is currently in fullscreen mode.\n * @returns {boolean}\n */\n isFullscreen() {\n return this.invoke('fullscreen.isActive') === true;\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 * Teardown itself is synchronous; the returned promise only settles once the\n * closing auto-save has finished, so `await editor.destroy()` is worth doing\n * when using an async `autoSaveAdapter`. Ignoring the return value is safe.\n * @returns {Promise<void>}\n */\n destroy() {\n if (!this._alive) return this._destroyPromise ?? Promise.resolve();\n\n // Start the final auto-save before tearing anything down. `_listeners` is\n // deliberately kept alive until this settles, otherwise the closing\n // autoSave/autoSaveError event fires into an already-cleared listener map\n // and an async adapter's last write completes silently.\n const pendingFlush = this._pendingAutoSave != null\n ? this.flushAutoSave().catch(() => {})\n : null;\n\n this._modules.forEach((module) => {\n if (typeof module.destroy === 'function') module.destroy();\n });\n this._modules.clear();\n\n for (const { plugin } of this._plugins.values()) {\n if (typeof plugin.uninstall === 'function') {\n try { plugin.uninstall(this); } catch (_) { void _; }\n }\n }\n this._plugins.clear();\n\n this._disposers.forEach((d) => d());\n this._disposers = [];\n\n const container = this.layoutInfo.container;\n const wasDark = container?.classList.contains('an-theme-dark');\n const wasAuto = container?.classList.contains('an-theme-auto');\n if (container?.parentNode) {\n // Restore original element\n this.targetEl.style.display = '';\n container.remove();\n }\n // Clean up body theme classes if no other editors of that type remain\n if (wasDark && !document.querySelector('.an-container.an-theme-dark')) {\n document.body.classList.remove('an-theme-dark');\n }\n if (wasAuto && !document.querySelector('.an-container.an-theme-auto')) {\n document.body.classList.remove('an-theme-auto');\n }\n\n if (typeof this.options.onDestroy === 'function') {\n this.options.onDestroy(this);\n }\n\n this._alive = false;\n\n // Resolves once the closing auto-save (if any) has finished. Callers using\n // an async autoSaveAdapter can `await editor.destroy()` to be sure the last\n // write landed before unloading.\n this._destroyPromise = Promise.resolve(pendingFlush).then(() => {\n this._listeners.clear();\n });\n return this._destroyPromise;\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Syncs editor HTML back into the original textarea/input for form submission.\n */\n _syncToTarget(html) {\n if (this.targetEl.tagName === 'TEXTAREA' || this.targetEl.tagName === 'INPUT') {\n /** @type {HTMLInputElement} */ (this.targetEl).value = typeof html === 'string' ? html : 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.flat();\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 * Every field is a lazy getter rather than a value computed at module load.\n * This module is re-exported from the package entry point, so reading\n * `navigator` eagerly meant that merely `import`ing autumnnote threw\n * `ReferenceError: navigator is not defined` under SSR on any runtime without\n * a global `navigator` — including Node 20, which package.json still supports.\n * Nothing inside the library reads these fields, so the crash happened before\n * an editor was ever created.\n */\n\n/** @returns {string} the current user agent, or '' when there is no navigator (SSR). */\nfunction ua() {\n return globalThis.navigator?.userAgent ?? '';\n}\n\nexport const env = {\n /** True if browser is Chrome (excludes Edge, whose UA also contains \"Chrome/\") */\n get isChrome() { return /Chrome\\//.test(ua()) && !/Edg\\//.test(ua()); },\n /** True if browser is Firefox */\n get isFF() { return /Firefox\\//.test(ua()); },\n /** True if browser is Safari (not Chrome) */\n get isSafari() { return /^((?!chrome|android).)*safari/i.test(ua()); },\n /** True if browser is Edge (Chromium) */\n get isEdge() { return /Edg\\//.test(ua()); },\n /** True if running on macOS */\n get isMac() { return /Macintosh/.test(ua()); },\n /** True if running on mobile */\n get isMobile() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua()); },\n /** True if touch is supported */\n get isTouch() {\n return 'ontouchstart' in globalThis || (globalThis.navigator?.maxTouchPoints ?? 0) > 0;\n },\n /** Modifier key name depending on platform */\n get modifierKey() { return /Macintosh/.test(ua()) ? '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\n// @ts-ignore\nimport '../styles/autumnnote.scss';\nimport { Context, _customModules, _globalPlugins } from './Context.js';\nimport { registerButton, buttons } from './module/Buttons.js';\nimport { defaultOptions } from './settings.js';\nimport { registerLocale } from './i18n/index.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, registerLocale } 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(/** @type {HTMLElement} */ (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 /**\n * Installs a plugin globally — applied to every future editor instance.\n * Plugin `buttons` are registered to the global button registry immediately\n * so they are available when Toolbar initialises inside create().\n * Plugin `install()` is called after all built-in modules have initialised.\n * @param {object} plugin - { name, version?, buttons?, install?, uninstall? }\n * @param {object} [options] - Forwarded to plugin.install(context, options)\n * @returns {typeof AutumnNote}\n */\n use(plugin, options = {}) {\n if (!plugin || typeof plugin.name !== 'string') {\n throw new TypeError('[AutumnNote] AutumnNote.use: plugin must have a string `name` property.');\n }\n if (_globalPlugins.has(plugin.name)) {\n console.warn(`[AutumnNote] Plugin \"${plugin.name}\" already registered globally. Skipping.`);\n return this;\n }\n if (Array.isArray(plugin.buttons)) {\n plugin.buttons.forEach((b) => registerButton(b));\n }\n _globalPlugins.set(plugin.name, { plugin, options });\n return this;\n },\n\n /**\n * Returns true if a plugin with the given name has been registered globally.\n * @param {string} name\n * @returns {boolean}\n */\n hasPlugin(name) { return _globalPlugins.has(name); },\n\n /**\n * Registers a single button definition in the global button registry.\n * After create(), call ctx.invoke('toolbar.rebuild') to render new buttons.\n * @param {object} btnDef - ButtonDef-compatible object with a `name` string\n * @returns {typeof AutumnNote}\n */\n registerButton(btnDef) { registerButton(btnDef); return this; },\n\n /**\n * Registers a locale so `lang: '<code>'` can select it.\n * Only English ships in the ESM bundle — import others from\n * `autumnnote/i18n/<code>` and register them here.\n * @param {string} code\n * @param {object} locale\n */\n registerLocale(code, locale) { registerLocale(code, locale); return this; },\n\n /** Registers a slash-menu command for future editor instances. */\n registerSlashCommand(command) {\n if (!command?.id || typeof command.run !== 'function') {\n throw new TypeError('[AutumnNote] Slash command requires an id and run(context) function.');\n }\n const commands = defaultOptions.slashCommands;\n const index = commands.findIndex((item) => item.id === command.id);\n if (index >= 0) commands[index] = command;\n else commands.push(command);\n return this;\n },\n\n /** All pre-built button definitions — accessible in every module format including UMD/CJS. */\n buttons,\n\n /** Library version */\n version: '2.2.0',\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 /** @type {Element[]} */ (Array.from(selector));\n }\n return [];\n}\n\nexport default AutumnNote;\n"],"mappings":"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"}