@noseberry/nbd-editor 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -10
- package/dist/nbd-editor.cjs.js +1 -1
- package/dist/nbd-editor.cjs.js.map +1 -1
- package/dist/nbd-editor.css +1 -1
- package/dist/nbd-editor.d.ts +151 -4
- package/dist/nbd-editor.esm.js +1 -1
- package/dist/nbd-editor.esm.js.map +1 -1
- package/dist/nbd-editor.umd.js +1 -1
- package/dist/nbd-editor.umd.js.map +1 -1
- package/package.json +10 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nbd-editor.umd.js","sources":["../src/utils/EventEmitter.js","../src/utils/dom.js","../src/utils/icons.js","../src/core/BlockManager.js","../src/core/MediaUploader.js","../src/core/DragDrop.js","../src/blocks/registry.js","../src/blocks/BlockRenderer.js","../src/ui/Header.js","../src/ui/Toolbar.js","../src/ui/InserterPanel.js","../src/ui/SettingsPanel.js","../src/ui/SlashMenu.js","../src/ui/StatusBar.js","../src/NBDEditor.js","../src/react/ReactNBDEditor.js"],"sourcesContent":["/**\n * Lightweight event emitter for editor internals.\n */\nexport class EventEmitter {\n constructor() {\n this._listeners = {};\n }\n\n on(event, fn) {\n (this._listeners[event] ||= []).push(fn);\n return () => this.off(event, fn);\n }\n\n off(event, fn) {\n const list = this._listeners[event];\n if (!list) return;\n this._listeners[event] = list.filter((f) => f !== fn);\n }\n\n emit(event, ...args) {\n (this._listeners[event] || []).forEach((fn) => fn(...args));\n }\n\n once(event, fn) {\n const wrapper = (...args) => {\n this.off(event, wrapper);\n fn(...args);\n };\n this.on(event, wrapper);\n }\n}\n","/**\n * DOM helper utilities.\n */\n\nexport function el(tag, attrs = {}, children = []) {\n const node = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n if (k === 'className') node.className = v;\n else if (k === 'style' && typeof v === 'object') Object.assign(node.style, v);\n else if (k === 'dataset' && typeof v === 'object') {\n for (const [dk, dv] of Object.entries(v)) node.dataset[dk] = dv;\n } else if (k.startsWith('on') && typeof v === 'function') {\n node.addEventListener(k.slice(2).toLowerCase(), v);\n } else if (k === 'contentEditable') {\n node.contentEditable = v;\n } else if (k === 'innerHTML') {\n node.innerHTML = v;\n } else {\n node.setAttribute(k, v);\n }\n }\n for (const child of (Array.isArray(children) ? children : [children])) {\n if (typeof child === 'string') node.appendChild(document.createTextNode(child));\n else if (child instanceof Node) node.appendChild(child);\n }\n return node;\n}\n\nexport function qs(sel, root = document) {\n return root.querySelector(sel);\n}\n\nexport function qsa(sel, root = document) {\n return [...root.querySelectorAll(sel)];\n}\n\nexport function generateId() {\n return 'blk_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);\n}\n\nexport function stripHTML(html) {\n const tmp = document.createElement('div');\n tmp.innerHTML = html;\n return tmp.textContent || '';\n}\n\nexport function getCaretRect() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n return range.getBoundingClientRect();\n}\n\nexport function placeCaretAtEnd(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nexport function placeCaretAtStart(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n","/**\n * SVG icons used throughout the editor.\n */\n\nconst svg = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${inner}</svg>`;\n\nconst filled = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"currentColor\">${inner}</svg>`;\n\nexport const icons = {\n plus: svg('<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>'),\n undo: svg('<path d=\"M3 10h13a4 4 0 010 8H7\"/><path d=\"M3 10l4-4M3 10l4 4\"/>'),\n redo: svg('<path d=\"M21 10H8a4 4 0 000 8h9\"/><path d=\"M21 10l-4-4M21 10l-4 4\"/>'),\n listView: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"/>'),\n settings: svg('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\"/>'),\n moreVert: filled('<circle cx=\"12\" cy=\"5\" r=\"1.5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\"/><circle cx=\"12\" cy=\"19\" r=\"1.5\"/>'),\n bold: '<b>B</b>',\n italic: '<i>I</i>',\n underline: '<u>U</u>',\n strikethrough: '<s>S</s>',\n link: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n code: svg('<polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/>'),\n alignLeft: svg('<line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"/>'),\n alignCenter: svg('<line x1=\"18\" y1=\"10\" x2=\"6\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"18\" y1=\"18\" x2=\"6\" y2=\"18\"/>'),\n alignRight: svg('<line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"/>'),\n image: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>'),\n heading: '<b>H</b>',\n paragraph: '<span style=\"font-size:16px\">¶</span>',\n quote: '<span style=\"font-size:18px\">❝</span>',\n list: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" 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 orderedList: svg('<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\"/><text x=\"3\" y=\"8\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">1</text><text x=\"3\" y=\"14\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">2</text><text x=\"3\" y=\"20\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">3</text>'),\n separator: svg('<line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/>'),\n table: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><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 button: svg('<rect x=\"3\" y=\"7\" width=\"18\" height=\"10\" rx=\"3\"/>'),\n columns: svg('<rect x=\"3\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/>'),\n spacer: svg('<path d=\"M12 5v14M5 12h14\"/>', '0 0 24 24'),\n embed: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n gallery: svg('<rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"2\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/>'),\n video: svg('<polygon points=\"5 3 19 12 5 21 5 3\"/>'),\n audio: svg('<path d=\"M9 18V5l12-2v13\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><circle cx=\"18\" cy=\"16\" r=\"3\"/>'),\n file: svg('<path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/>'),\n dragHandle: filled('<circle cx=\"9\" cy=\"5\" r=\"1.2\"/><circle cx=\"15\" cy=\"5\" r=\"1.2\"/><circle cx=\"9\" cy=\"10\" r=\"1.2\"/><circle cx=\"15\" cy=\"10\" r=\"1.2\"/><circle cx=\"9\" cy=\"15\" r=\"1.2\"/><circle cx=\"15\" cy=\"15\" r=\"1.2\"/><circle cx=\"9\" cy=\"20\" r=\"1.2\"/><circle cx=\"15\" cy=\"20\" r=\"1.2\"/>'),\n arrowUp: svg('<polyline points=\"18 15 12 9 6 15\"/>'),\n arrowDown: svg('<polyline points=\"6 9 12 15 18 9\"/>'),\n trash: svg('<polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/>'),\n close: svg('<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>'),\n check: svg('<polyline points=\"20 6 9 17 4 12\"/>'),\n inlineCode: '<span style=\"font-family:monospace;font-size:13px\"></></span>',\n upload: svg('<path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\"/><polyline points=\"17 8 12 3 7 8\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"/>'),\n externalLink: svg('<path d=\"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/>'),\n html: '<span style=\"font-family:monospace;font-size:11px\"><HTML></span>',\n pullquote: svg('<path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/>'),\n};\n","import { generateId } from '../utils/dom.js';\nimport { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Manages the block data model: add, remove, move, update, and undo/redo.\n */\nexport class BlockManager extends EventEmitter {\n constructor() {\n super();\n this.blocks = [];\n this._undoStack = [];\n this._redoStack = [];\n this._maxHistory = 100;\n this._undoStack.push(JSON.stringify(this.blocks));\n }\n\n /* ---- CRUD ---- */\n\n addBlock(type, data = {}, afterId = null) {\n const block = {\n id: generateId(),\n type,\n content: '',\n attrs: {},\n ...data,\n };\n\n if (afterId) {\n const idx = this.blocks.findIndex((b) => b.id === afterId);\n this.blocks.splice(idx + 1, 0, block);\n } else {\n this.blocks.push(block);\n }\n\n this._pushUndo();\n this.emit('block:added', block);\n this.emit('change', this.blocks);\n return block;\n }\n\n removeBlock(id) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n if (idx === -1) return;\n if (this.blocks.length <= 1) return; // keep at least one block\n const [removed] = this.blocks.splice(idx, 1);\n this._pushUndo();\n this.emit('block:removed', removed, idx);\n this.emit('change', this.blocks);\n return removed;\n }\n\n updateBlock(id, patch) {\n const block = this.getBlock(id);\n if (!block) return;\n Object.assign(block, patch);\n this.emit('block:updated', block);\n this.emit('change', this.blocks);\n }\n\n changeBlockType(id, newType) {\n const block = this.getBlock(id);\n if (!block) return;\n block.type = newType;\n this._pushUndo();\n this.emit('block:typeChanged', block);\n this.emit('change', this.blocks);\n }\n\n moveBlock(id, direction) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n const newIdx = idx + direction;\n if (newIdx < 0 || newIdx >= this.blocks.length) return;\n [this.blocks[idx], this.blocks[newIdx]] = [this.blocks[newIdx], this.blocks[idx]];\n this._pushUndo();\n this.emit('block:moved', this.blocks[newIdx], direction);\n this.emit('change', this.blocks);\n }\n\n duplicateBlock(id) {\n const block = this.getBlock(id);\n if (!block) return;\n const clone = { ...block, id: generateId(), content: block.content, attrs: { ...block.attrs } };\n const idx = this.blocks.findIndex((b) => b.id === id);\n this.blocks.splice(idx + 1, 0, clone);\n this._pushUndo();\n this.emit('block:added', clone);\n this.emit('change', this.blocks);\n return clone;\n }\n\n /* ---- Queries ---- */\n\n getBlock(id) {\n return this.blocks.find((b) => b.id === id) || null;\n }\n\n getIndex(id) {\n return this.blocks.findIndex((b) => b.id === id);\n }\n\n getPrevBlock(id) {\n const idx = this.getIndex(id);\n return idx > 0 ? this.blocks[idx - 1] : null;\n }\n\n getNextBlock(id) {\n const idx = this.getIndex(id);\n return idx < this.blocks.length - 1 ? this.blocks[idx + 1] : null;\n }\n\n /* ---- Serialization ---- */\n\n toJSON() {\n return this.blocks.map((b) => ({ ...b }));\n }\n\n fromJSON(data) {\n this.blocks = data.map((b) => ({ ...b }));\n this._undoStack = [JSON.stringify(this.blocks)];\n this._redoStack = [];\n this.emit('change', this.blocks);\n }\n\n toHTML() {\n return this.blocks.map((b) => this.blockToHTML(b)).join('\\n');\n }\n\n toHTMLBlocks() {\n return this.blocks.map((b) => ({\n ...b,\n html: this.blockToHTML(b),\n }));\n }\n\n blockToHTML(block) {\n return blockToHTML(block);\n }\n\n /* ---- Undo / Redo ---- */\n\n _pushUndo() {\n const next = JSON.stringify(this.blocks);\n const last = this._undoStack[this._undoStack.length - 1];\n if (next === last) return;\n this._undoStack.push(next);\n if (this._undoStack.length > this._maxHistory) this._undoStack.shift();\n this._redoStack = [];\n }\n\n saveSnapshot() {\n this._pushUndo();\n }\n\n undo() {\n if (this._undoStack.length < 2) return false;\n this._redoStack.push(this._undoStack.pop());\n this.blocks = JSON.parse(this._undoStack[this._undoStack.length - 1]);\n this.emit('change', this.blocks);\n return true;\n }\n\n redo() {\n if (this._redoStack.length === 0) return false;\n const state = this._redoStack.pop();\n this._undoStack.push(state);\n this.blocks = JSON.parse(state);\n this.emit('change', this.blocks);\n return true;\n }\n\n /* ---- Stats ---- */\n\n getWordCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent + ' ';\n }\n }\n const words = text.trim().split(/\\s+/).filter((w) => w.length > 0);\n return words.length;\n }\n\n getCharCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent;\n }\n }\n return text.replace(/\\s/g, '').length;\n }\n}\n\n/* ---- Helpers ---- */\n\n/**\n * Escape a string for safe use inside an HTML attribute value.\n * Prevents XSS via attribute injection (e.g. `\" onload=\"alert(1)`).\n */\nfunction _escAttr(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\n/**\n * Escape a string for safe use as HTML text content.\n */\nfunction _escText(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nfunction blockToHTML(block) {\n const c = block.content || '';\n switch (block.type) {\n case 'paragraph':\n return _containsBlockMarkup(c) ? c : `<p>${c}</p>`;\n case 'heading':\n return `<h2>${c}</h2>`;\n case 'heading-3':\n return `<h3>${c}</h3>`;\n case 'heading-4':\n return `<h4>${c}</h4>`;\n case 'quote':\n return `<blockquote>${c}</blockquote>`;\n case 'code':\n return `<pre><code>${_escText(c)}</code></pre>`;\n case 'list':\n return `<ul>${c}</ul>`;\n case 'ordered-list':\n return `<ol>${c}</ol>`;\n case 'image': {\n if (!c) return '';\n const width = Number(block.attrs?.width);\n const style = Number.isFinite(width) ? ` style=\"width:${Math.max(10, Math.min(100, Math.round(width)))}%\"` : '';\n return `<figure><img src=\"${_escAttr(c)}\" alt=\"${_escAttr(block.attrs?.alt || '')}\"${style}/>${block.attrs?.caption ? `<figcaption>${block.attrs.caption}</figcaption>` : ''}</figure>`;\n }\n case 'separator':\n return '<hr/>';\n case 'spacer':\n return `<div style=\"height:${Number(block.attrs?.height) || 48}px\"></div>`;\n case 'table':\n return c || '<table></table>';\n case 'button':\n return `<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"${_escAttr(block.attrs?.url || '#')}\">${c || 'Button'}</a></div>`;\n case 'columns':\n return `<div class=\"wp-block-columns\">${c}</div>`;\n case 'embed':\n return `<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">${c}</div></figure>`;\n case 'gallery':\n return `<figure class=\"wp-block-gallery\">${c}</figure>`;\n case 'video':\n return c ? `<figure class=\"wp-block-video\"><video controls src=\"${_escAttr(c)}\"></video></figure>` : '';\n case 'audio':\n return c ? `<figure class=\"wp-block-audio\"><audio controls src=\"${_escAttr(c)}\"></audio></figure>` : '';\n case 'file':\n return c ? `<div class=\"wp-block-file\"><a href=\"${_escAttr(c)}\">${_escText(block.attrs?.filename || 'Download')}</a></div>` : '';\n case 'html':\n return c;\n case 'pullquote':\n return `<figure class=\"wp-block-pullquote\"><blockquote>${c}</blockquote></figure>`;\n default:\n return `<p>${c}</p>`;\n }\n}\n\nfunction _containsBlockMarkup(html) {\n if (!html || typeof html !== 'string') return false;\n return /<(h[1-6]|p|div|section|article|blockquote|ul|ol|li|table|thead|tbody|tr|td|th|figure|figcaption|img|pre|hr)\\b/i.test(html);\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Handles media uploads: images, video, audio, files.\n * Supports custom upload handlers, drag-and-drop, clipboard paste, and local preview.\n */\nexport class MediaUploader extends EventEmitter {\n constructor(options = {}) {\n super();\n this.uploadHandler = options.uploadHandler || null; // async (file) => { url, id }\n this.maxFileSize = options.maxFileSize || 10 * 1024 * 1024; // 10MB\n this.allowedImageTypes = options.allowedImageTypes || ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];\n this.allowedVideoTypes = options.allowedVideoTypes || ['video/mp4', 'video/webm', 'video/ogg'];\n this.allowedAudioTypes = options.allowedAudioTypes || ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/webm'];\n this._fileInput = null;\n }\n\n /**\n * Create a hidden file input and trigger it.\n */\n openFilePicker(accept = 'image/*', multiple = false) {\n return new Promise((resolve) => {\n if (this._fileInput) this._fileInput.remove();\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = accept;\n input.multiple = multiple;\n input.style.display = 'none';\n document.body.appendChild(input);\n this._fileInput = input;\n\n input.addEventListener('change', () => {\n const files = [...input.files];\n input.remove();\n this._fileInput = null;\n resolve(files);\n });\n\n input.addEventListener('cancel', () => {\n input.remove();\n this._fileInput = null;\n resolve([]);\n });\n\n input.click();\n });\n }\n\n /**\n * Process a file: validate, generate local preview, then optionally upload.\n * Returns { localUrl, remoteUrl?, file, error? }\n */\n async processFile(file) {\n // Validate size\n if (file.size > this.maxFileSize) {\n const err = `File \"${file.name}\" exceeds the ${(this.maxFileSize / 1024 / 1024).toFixed(0)}MB limit.`;\n this.emit('error', err);\n return { error: err, file };\n }\n\n // Generate local preview\n const localUrl = await this._readAsDataURL(file);\n this.emit('preview', { file, localUrl });\n\n // If a custom upload handler is provided, use it\n if (this.uploadHandler) {\n try {\n this.emit('upload:start', { file });\n const result = await this.uploadHandler(file);\n this.emit('upload:complete', { file, ...result });\n return { localUrl, remoteUrl: result.url, file, id: result.id };\n } catch (err) {\n this.emit('upload:error', { file, error: err });\n return { localUrl, file, error: err.message || 'Upload failed' };\n }\n }\n\n // No remote handler — just use local data URL\n return { localUrl, file };\n }\n\n /**\n * Process multiple files.\n */\n async processFiles(files) {\n return Promise.all(files.map((f) => this.processFile(f)));\n }\n\n /**\n * Handle a paste event for images.\n */\n async handlePaste(clipboardData) {\n const items = [...(clipboardData.items || [])];\n const imageItems = items.filter((item) => item.type.startsWith('image/'));\n if (imageItems.length === 0) return null;\n\n const files = imageItems.map((item) => item.getAsFile()).filter(Boolean);\n if (files.length === 0) return null;\n\n return this.processFiles(files);\n }\n\n /**\n * Handle drag-and-drop of files.\n */\n async handleDrop(dataTransfer) {\n const files = [...(dataTransfer.files || [])];\n if (files.length === 0) return null;\n return this.processFiles(files);\n }\n\n /**\n * Determine media type from file.\n */\n getMediaType(file) {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type.startsWith('video/')) return 'video';\n if (file.type.startsWith('audio/')) return 'audio';\n return 'file';\n }\n\n /**\n * Read file as data URL.\n */\n _readAsDataURL(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n }\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Drag-and-drop reordering for blocks.\n */\nexport class DragDrop extends EventEmitter {\n constructor(container) {\n super();\n this.container = container;\n this._dragging = null;\n this._placeholder = null;\n this._offsetY = 0;\n this._bound = {};\n this._enabled = true;\n }\n\n enable() {\n this._enabled = true;\n }\n\n disable() {\n this._enabled = false;\n }\n\n /**\n * Initialise drag on a handle element within a block wrapper.\n */\n initDrag(handleEl, wrapperEl, blockId) {\n handleEl.setAttribute('draggable', 'true');\n handleEl.style.cursor = 'grab';\n\n handleEl.addEventListener('dragstart', (e) => {\n if (!this._enabled) return e.preventDefault();\n this._dragging = { el: wrapperEl, id: blockId };\n wrapperEl.style.opacity = '0.4';\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', blockId);\n this.emit('drag:start', blockId);\n });\n\n handleEl.addEventListener('dragend', () => {\n if (this._dragging) {\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n }\n this._removePlaceholder();\n this.emit('drag:end');\n });\n\n wrapperEl.addEventListener('dragover', (e) => {\n if (!this._dragging || this._dragging.id === blockId) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._showPlaceholder(wrapperEl, position);\n });\n\n wrapperEl.addEventListener('drop', (e) => {\n e.preventDefault();\n if (!this._dragging) return;\n const fromId = this._dragging.id;\n const toId = blockId;\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._removePlaceholder();\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n\n this.emit('drop', { fromId, toId, position });\n });\n }\n\n _showPlaceholder(referenceEl, position) {\n if (!this._placeholder) {\n this._placeholder = document.createElement('div');\n this._placeholder.className = 'fe-drag-placeholder';\n this._placeholder.style.cssText =\n 'height:4px;background:#2271b1;border-radius:2px;margin:4px 0;transition:all 0.15s;';\n }\n if (position === 'before') {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl);\n } else {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl.nextSibling);\n }\n }\n\n _removePlaceholder() {\n if (this._placeholder && this._placeholder.parentNode) {\n this._placeholder.parentNode.removeChild(this._placeholder);\n }\n }\n}\n","import { icons } from '../utils/icons.js';\n\n/**\n * Block type registry. Each entry describes a block type and how to render it.\n */\nexport const BLOCK_TYPES = {\n paragraph: {\n label: 'Paragraph',\n description: 'Start with the building block of all narrative.',\n icon: icons.paragraph,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Type / to choose a block',\n className: '',\n },\n heading: {\n label: 'Heading 2',\n description: 'Introduce new sections and organize content.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h2',\n placeholder: 'Heading 2',\n className: 'fe-heading-2',\n },\n 'heading-3': {\n label: 'Heading 3',\n description: 'A smaller heading for subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h3',\n placeholder: 'Heading 3',\n className: 'fe-heading-3',\n },\n 'heading-4': {\n label: 'Heading 4',\n description: 'A small heading for nested subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h4',\n placeholder: 'Heading 4',\n className: 'fe-heading-4',\n },\n list: {\n label: 'List',\n description: 'Create a bulleted list.',\n icon: icons.list,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-list-block',\n },\n 'ordered-list': {\n label: 'Ordered List',\n description: 'Create a numbered list.',\n icon: icons.orderedList,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-ordered-list-block',\n },\n quote: {\n label: 'Quote',\n description: 'Give quoted text visual emphasis.',\n icon: icons.quote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write quote...',\n className: 'fe-quote',\n },\n pullquote: {\n label: 'Pullquote',\n description: 'Highlight a key quote from your content.',\n icon: icons.pullquote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write pullquote...',\n className: 'fe-pullquote',\n },\n code: {\n label: 'Code',\n description: 'Display code snippets that respect your spacing.',\n icon: icons.code,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write code...',\n className: 'fe-code-block',\n },\n html: {\n label: 'Custom HTML',\n description: 'Add custom HTML code.',\n icon: icons.html,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write HTML...',\n className: 'fe-html-block',\n },\n image: {\n label: 'Image',\n description: 'Insert an image to make a visual statement.',\n icon: icons.image,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n gallery: {\n label: 'Gallery',\n description: 'Display multiple images in a gallery.',\n icon: icons.gallery,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n video: {\n label: 'Video',\n description: 'Embed a video from your media library or URL.',\n icon: icons.video,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n audio: {\n label: 'Audio',\n description: 'Embed an audio file.',\n icon: icons.audio,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n file: {\n label: 'File',\n description: 'Add a link to a downloadable file.',\n icon: icons.file,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n separator: {\n label: 'Separator',\n description: 'Create a break between ideas or sections.',\n icon: icons.separator,\n category: 'design',\n hasContent: false,\n },\n spacer: {\n label: 'Spacer',\n description: 'Add white space between blocks.',\n icon: icons.spacer,\n category: 'design',\n hasContent: false,\n },\n columns: {\n label: 'Columns',\n description: 'Display content in multiple columns.',\n icon: icons.columns,\n category: 'design',\n hasContent: false,\n },\n table: {\n label: 'Table',\n description: 'Insert a table for sharing data.',\n icon: icons.table,\n category: 'design',\n hasContent: false,\n },\n button: {\n label: 'Button',\n description: 'Prompt visitors to take action with a button.',\n icon: icons.button,\n category: 'design',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Add text...',\n className: 'fe-button-block',\n },\n embed: {\n label: 'Embed',\n description: 'Embed content from YouTube, Twitter, etc.',\n icon: icons.embed,\n category: 'media',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Enter URL to embed...',\n className: 'fe-embed-block',\n },\n};\n\nexport const CATEGORIES = [\n { id: 'text', label: 'Text' },\n { id: 'media', label: 'Media' },\n { id: 'design', label: 'Design' },\n];\n\n/**\n * Get blocks for a category.\n */\nexport function getBlocksByCategory(catId) {\n return Object.entries(BLOCK_TYPES)\n .filter(([, def]) => def.category === catId)\n .map(([type, def]) => ({ type, ...def }));\n}\n\n/**\n * Search blocks by query.\n */\nexport function searchBlocks(query) {\n const q = query.toLowerCase();\n return Object.entries(BLOCK_TYPES)\n .filter(([type, def]) => type.includes(q) || def.label.toLowerCase().includes(q) || def.description.toLowerCase().includes(q))\n .map(([type, def]) => ({ type, ...def }));\n}\n","import { el, placeCaretAtEnd } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { BLOCK_TYPES } from './registry.js';\n\n/**\n * Creates the DOM for a single block based on its type and data.\n */\nexport class BlockRenderer {\n constructor(editor) {\n this.editor = editor;\n }\n\n render(block) {\n const def = BLOCK_TYPES[block.type];\n if (!def) return this._renderParagraph(block);\n\n if (def.isMedia) return this._renderMediaBlock(block, def);\n if (def.hasContent) return this._renderContentBlock(block, def);\n\n // Non-content blocks\n switch (block.type) {\n case 'separator': return this._renderSeparator(block);\n case 'spacer': return this._renderSpacer(block);\n case 'columns': return this._renderColumns(block);\n case 'table': return this._renderTable(block);\n default: return this._renderParagraph(block);\n }\n }\n\n /* ---- Content Blocks (editable) ---- */\n\n _renderContentBlock(block, def) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el(def.contentTag || 'div', {\n className: `fe-block-content ${def.className || ''}`.trim(),\n contentEditable: 'true',\n dataset: { \n placeholder: def.placeholder || '',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: isRawTextBlock ? '' : (block.content || '<br>'),\n });\n if (isRawTextBlock && block.content) {\n node.textContent = block.content;\n }\n\n this._bindContentEvents(node, block);\n return node;\n }\n\n _renderParagraph(block) {\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el('div', {\n className: 'fe-block-content',\n contentEditable: 'true',\n dataset: { \n placeholder: 'Type / to choose a block',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: block.content || '<br>',\n });\n this._bindContentEvents(node, block);\n return node;\n }\n\n /* ---- Media Blocks ---- */\n\n _renderMediaBlock(block, def) {\n const container = el('div', { className: `fe-block-media fe-block-${block.type}` });\n\n switch (block.type) {\n case 'image':\n return this._renderImageBlock(block, container);\n case 'gallery':\n return this._renderGalleryBlock(block, container);\n case 'video':\n return this._renderVideoBlock(block, container);\n case 'audio':\n return this._renderAudioBlock(block, container);\n case 'file':\n return this._renderFileBlock(block, container);\n default:\n return this._renderMediaPlaceholder(block, container, def);\n }\n }\n\n _renderImageBlock(block, container) {\n if (block.content) {\n const width = _normalizeImageWidth(block.attrs?.width);\n const fig = el('figure', { className: 'fe-image-figure' });\n const img = el('img', { src: block.content, alt: block.attrs?.alt || '' });\n img.style.width = `${width}%`;\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n img.style.display = 'block';\n fig.appendChild(img);\n\n // Caption\n const caption = el('figcaption', {\n className: 'fe-image-caption',\n contentEditable: 'true',\n dataset: { placeholder: 'Add caption...' },\n innerHTML: block.attrs?.caption || '',\n });\n caption.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs.caption = caption.innerHTML;\n });\n fig.appendChild(caption);\n\n // Toolbar overlay\n const overlay = el('div', { className: 'fe-image-overlay' });\n const replaceBtn = el('button', {\n className: 'fe-img-overlay-btn',\n innerHTML: 'Replace',\n onClick: () => this._triggerImageUpload(block),\n });\n const removeBtn = el('button', {\n className: 'fe-img-overlay-btn fe-img-overlay-btn-danger',\n innerHTML: 'Remove',\n onClick: () => {\n block.content = '';\n block.attrs = {};\n this.editor.render();\n },\n });\n overlay.appendChild(replaceBtn);\n overlay.appendChild(removeBtn);\n fig.appendChild(overlay);\n\n const resizeHandle = el('button', {\n type: 'button',\n className: 'fe-image-resize-handle',\n title: 'Drag to resize image',\n });\n resizeHandle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.editor.selectBlock(block.id);\n\n const startX = e.clientX;\n const startWidth = img.getBoundingClientRect().width;\n const parentWidth = container.getBoundingClientRect().width || startWidth || 1;\n\n const onMove = (ev) => {\n const delta = ev.clientX - startX;\n const nextWidthPx = Math.max(80, Math.min(parentWidth, startWidth + delta));\n const nextPercent = _normalizeImageWidth((nextWidthPx / parentWidth) * 100);\n block.attrs = block.attrs || {};\n block.attrs.width = nextPercent;\n img.style.width = `${nextPercent}%`;\n };\n\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this.editor.statusBar.update();\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n fig.appendChild(resizeHandle);\n\n container.appendChild(fig);\n\n const sizeControls = el('div', { className: 'fe-image-size-controls' });\n [25, 50, 75, 100].forEach((pct) => {\n const btn = el('button', {\n type: 'button',\n className: `fe-img-size-btn ${width === pct ? 'is-active' : ''}`.trim(),\n innerHTML: `${pct}%`,\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.width = pct;\n this.editor.render();\n },\n });\n sizeControls.appendChild(btn);\n });\n container.appendChild(sizeControls);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.image);\n }\n\n return container;\n }\n\n _renderGalleryBlock(block, container) {\n const images = block.attrs?.images || [];\n if (images.length > 0) {\n const grid = el('div', { className: 'fe-gallery-grid' });\n images.forEach((src, i) => {\n const item = el('div', { className: 'fe-gallery-item' });\n item.appendChild(el('img', { src, alt: '' }));\n const removeBtn = el('button', {\n className: 'fe-gallery-remove',\n innerHTML: '×',\n onClick: () => {\n images.splice(i, 1);\n this.editor.render();\n },\n });\n item.appendChild(removeBtn);\n grid.appendChild(item);\n });\n container.appendChild(grid);\n\n const addMore = el('button', {\n className: 'fe-gallery-add',\n innerHTML: '+ Add Images',\n onClick: () => this._triggerGalleryUpload(block),\n });\n container.appendChild(addMore);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.gallery);\n }\n return container;\n }\n\n _renderVideoBlock(block, container) {\n if (block.content) {\n const video = el('video', { src: block.content });\n video.controls = true;\n video.style.maxWidth = '100%';\n video.style.borderRadius = '4px';\n container.appendChild(video);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.video);\n }\n return container;\n }\n\n _renderAudioBlock(block, container) {\n if (block.content) {\n const audio = el('audio', { src: block.content });\n audio.controls = true;\n audio.style.width = '100%';\n container.appendChild(audio);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.audio);\n }\n return container;\n }\n\n _renderFileBlock(block, container) {\n if (block.content) {\n const wrapper = el('div', { className: 'fe-file-wrapper' });\n\n const infoDiv = el('div', { className: 'fe-file-info' });\n infoDiv.appendChild(el('span', { className: 'fe-file-icon', innerHTML: icons.file }));\n infoDiv.appendChild(el('span', { className: 'fe-file-name' }, [block.attrs?.filename || 'File']));\n infoDiv.appendChild(el('span', { className: 'fe-file-size' }, [block.attrs?.filesize || '']));\n wrapper.appendChild(infoDiv);\n\n const downloadLink = el('a', { className: 'fe-file-download', href: block.content, download: '' }, ['Download']);\n wrapper.appendChild(downloadLink);\n\n container.appendChild(wrapper);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.file);\n }\n return container;\n }\n\n _renderMediaPlaceholder(block, container, def) {\n const placeholder = el('div', { className: 'fe-media-placeholder' });\n\n const iconEl = el('div', { className: 'fe-media-placeholder-icon', innerHTML: def.icon });\n const label = el('p', { className: 'fe-media-placeholder-label' }, [def.label]);\n const desc = el('p', { className: 'fe-media-placeholder-desc' }, ['Upload a file or pick one from your media library.']);\n\n const btnRow = el('div', { className: 'fe-media-placeholder-actions' });\n\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: `${icons.upload} Upload`,\n onClick: () => this._handleMediaUpload(block),\n });\n btnRow.appendChild(uploadBtn);\n\n // URL input for embeds, video, audio\n if (['embed', 'video', 'audio'].includes(block.type)) {\n const urlInput = el('input', {\n type: 'text',\n className: 'fe-media-url-input',\n placeholder: 'Or paste a URL...',\n });\n urlInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n block.content = urlInput.value;\n this.editor.render();\n }\n });\n btnRow.appendChild(urlInput);\n }\n\n placeholder.appendChild(iconEl);\n placeholder.appendChild(label);\n placeholder.appendChild(desc);\n placeholder.appendChild(btnRow);\n container.appendChild(placeholder);\n\n // Drop zone\n this._setupDropZone(placeholder, block);\n\n return container;\n }\n\n /* ---- Non-content Blocks ---- */\n\n _renderSeparator(block) {\n const node = el('div', { className: 'fe-block-separator' });\n node.appendChild(el('hr'));\n return node;\n }\n\n _renderSpacer(block) {\n const height = block.attrs?.height || 48;\n const node = el('div', {\n className: 'fe-block-spacer',\n style: { height: height + 'px' },\n });\n\n // Resize handle\n const handle = el('div', { className: 'fe-spacer-handle' });\n let startY, startH;\n handle.addEventListener('mousedown', (e) => {\n startY = e.clientY;\n startH = height;\n const onMove = (ev) => {\n const newH = Math.max(16, startH + ev.clientY - startY);\n node.style.height = newH + 'px';\n block.attrs = block.attrs || {};\n block.attrs.height = newH;\n };\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n node.appendChild(handle);\n return node;\n }\n\n _renderColumns(block) {\n const numCols = block.attrs?.columns || 2;\n const node = el('div', { className: 'fe-block-columns' });\n for (let i = 0; i < numCols; i++) {\n const col = el('div', {\n className: 'fe-column',\n contentEditable: 'true',\n dataset: { placeholder: `Column ${i + 1}` },\n innerHTML: block.attrs?.[`col${i}`] || '',\n });\n col.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs[`col${i}`] = col.innerHTML;\n });\n node.appendChild(col);\n }\n\n const controls = el('div', { className: 'fe-columns-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.columns = Math.max(1, Number(block.attrs.columns || numCols) + 1);\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '- Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n const current = Math.max(1, Number(block.attrs.columns || numCols));\n if (current <= 1) return;\n delete block.attrs[`col${current - 1}`];\n block.attrs.columns = current - 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n _renderTable(block) {\n const rows = block.attrs?.rows || 3;\n const cols = block.attrs?.cols || 3;\n const node = el('div', { className: 'fe-block-table' });\n const table = el('table');\n const data = block.attrs?.data || [];\n\n for (let r = 0; r < rows; r++) {\n const tr = el('tr');\n for (let c = 0; c < cols; c++) {\n const cellTag = r === 0 ? 'th' : 'td';\n const cell = el(cellTag, {\n contentEditable: 'true',\n innerHTML: data[r]?.[c] || '',\n });\n cell.addEventListener('input', () => {\n if (!block.attrs) block.attrs = {};\n if (!block.attrs.data) block.attrs.data = [];\n if (!block.attrs.data[r]) block.attrs.data[r] = [];\n block.attrs.data[r][c] = cell.innerHTML;\n });\n tr.appendChild(cell);\n }\n table.appendChild(tr);\n }\n\n node.appendChild(table);\n\n // Add row/column buttons\n const controls = el('div', { className: 'fe-table-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Row',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.rows = (block.attrs.rows || 3) + 1;\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.cols = (block.attrs.cols || 3) + 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n /* ---- Upload Helpers ---- */\n\n async _handleMediaUpload(block) {\n let accept = '*/*';\n if (block.type === 'image' || block.type === 'gallery') accept = 'image/*';\n else if (block.type === 'video') accept = 'video/*';\n else if (block.type === 'audio') accept = 'audio/*';\n\n const multiple = block.type === 'gallery';\n const files = await this.editor.mediaUploader.openFilePicker(accept, multiple);\n if (files.length === 0) return;\n\n if (block.type === 'gallery') {\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n block.content = result.remoteUrl || result.localUrl;\n if (block.type === 'file') {\n block.attrs = block.attrs || {};\n block.attrs.filename = files[0].name;\n block.attrs.filesize = _formatSize(files[0].size);\n }\n }\n }\n this.editor.render();\n }\n\n async _triggerImageUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (files.length === 0) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) block.content = result.remoteUrl || result.localUrl;\n this.editor.render();\n }\n\n async _triggerGalleryUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*', true);\n if (files.length === 0) return;\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n this.editor.render();\n }\n\n _setupDropZone(element, block) {\n element.addEventListener('dragover', (e) => {\n e.preventDefault();\n element.classList.add('fe-drop-active');\n });\n element.addEventListener('dragleave', () => {\n element.classList.remove('fe-drop-active');\n });\n element.addEventListener('drop', async (e) => {\n e.preventDefault();\n element.classList.remove('fe-drop-active');\n const results = await this.editor.mediaUploader.handleDrop(e.dataTransfer);\n if (results && results.length > 0) {\n if (block.type === 'gallery') {\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const res = results[0];\n if (!res.error) block.content = res.remoteUrl || res.localUrl;\n }\n this.editor.render();\n }\n });\n }\n\n /* ---- Content Events ---- */\n\n _bindContentEvents(node, block) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n\n // Helper to update empty state\n const updateEmptyState = () => {\n const text = node.textContent || '';\n const isEmpty = isRawTextBlock\n ? text.trim() === ''\n : text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '');\n node.dataset.empty = isEmpty ? 'true' : 'false';\n };\n\n // Update empty state initially\n updateEmptyState();\n\n // Ensure contenteditable gets focus when clicked\n node.addEventListener('mousedown', (e) => {\n // Let wrapper click handle first-time block selection to avoid losing focus on re-render\n if (this.editor._selectedBlockId !== block.id) return;\n // Stop propagation so wrapper click does not override caret placement on selected blocks\n e.stopPropagation();\n // Immediately focus on mousedown for better responsiveness\n if (document.activeElement !== node) {\n node.focus();\n // If empty (only has <br>), place caret correctly\n const text = node.textContent || '';\n if (text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '')) {\n // Ensure there's a <br> for cursor visibility\n if (node.innerHTML.trim() === '') {\n node.innerHTML = '<br>';\n }\n // Place caret after the <br>\n setTimeout(() => {\n const range = document.createRange();\n const sel = window.getSelection();\n range.selectNodeContents(node);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }, 0);\n }\n }\n });\n\n node.addEventListener('input', () => {\n if (isRawTextBlock) {\n block.content = node.textContent || '';\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n return;\n }\n\n // Clean up: if content is just <br> or empty, store as empty string\n let content = node.innerHTML.trim();\n if (content === '<br>' || content === '<br/>' || content === '') {\n content = '';\n // Keep the <br> in the DOM for cursor visibility, but don't save it\n if (!node.querySelector('br')) {\n node.innerHTML = '<br>';\n }\n }\n block.content = content;\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n });\n\n node.addEventListener('keydown', (e) => {\n this.editor._onBlockKeydown(e, block, node);\n });\n\n node.addEventListener('focus', () => {\n this.editor.selectBlock(block.id);\n });\n\n node.addEventListener('paste', (e) => {\n // Code blocks: plain text only\n if (block.type === 'code' || block.type === 'html') {\n e.preventDefault();\n const text = e.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n return;\n }\n\n // Image paste\n if (e.clipboardData.items) {\n const imageItems = [...e.clipboardData.items].filter((i) => i.type.startsWith('image/'));\n if (imageItems.length > 0) {\n e.preventDefault();\n this.editor.mediaUploader.handlePaste(e.clipboardData).then((results) => {\n if (results && results.length > 0) {\n const src = results[0].remoteUrl || results[0].localUrl;\n if (src) {\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n }\n }\n });\n return;\n }\n }\n });\n }\n}\n\nfunction _formatSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n}\n\nfunction _normalizeImageWidth(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return 100;\n return Math.max(10, Math.min(100, Math.round(numeric)));\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Top editor header bar: inserter button, undo/redo, status, save/publish, settings toggle.\n */\nexport class Header {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-header' });\n\n // Left\n const left = el('div', { className: 'fe-header-left' });\n\n // Block inserter toggle\n const inserterBtn = el('button', {\n className: 'fe-inserter-toggle',\n innerHTML: icons.plus,\n title: 'Toggle block inserter',\n onClick: (e) => this.editor.inserterPanel.toggle(e.currentTarget),\n });\n left.appendChild(inserterBtn);\n left.appendChild(el('span', { className: 'fe-sep' }));\n\n // Undo / Redo\n left.appendChild(this._iconBtn(icons.undo, 'Undo (Ctrl+Z)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.undo({ preferNative: inEditable });\n }));\n left.appendChild(this._iconBtn(icons.redo, 'Redo (Ctrl+Y)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.redo({ preferNative: inEditable });\n }));\n left.appendChild(el('span', { className: 'fe-sep' }));\n\n // List view\n left.appendChild(this._iconBtn(icons.listView, 'Document overview', () => {\n this.editor.emit('listView:toggle');\n }));\n\n this.el.appendChild(left);\n\n // Center spacer\n const center = el('div', { className: 'fe-header-center' });\n this.el.appendChild(center);\n\n // Right\n const right = el('div', { className: 'fe-header-right' });\n\n if (this.editor.options.showHeaderActions) {\n const draftBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Save draft',\n onClick: () => this.editor.save(),\n });\n right.appendChild(draftBtn);\n\n const publishBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Publish',\n onClick: () => this.editor.publish(),\n });\n right.appendChild(publishBtn);\n }\n\n if (this.editor.options.showSettingsPanel) {\n if (right.childNodes.length > 0) {\n right.appendChild(el('span', { className: 'fe-sep' }));\n }\n right.appendChild(this._iconBtn(icons.settings, 'Settings', () => {\n this.editor.settingsPanel.toggle();\n this.editor._updateCanvasMargin();\n }));\n }\n\n this.el.appendChild(right);\n return this.el;\n }\n\n setStatus(text, color) {\n // no-op: status text removed from header UI\n }\n\n _iconBtn(iconHTML, title, onClick) {\n return el('button', {\n className: 'fe-icon-btn',\n innerHTML: iconHTML,\n title,\n onClick,\n });\n }\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Floating block toolbar for formatting and block controls.\n */\nexport class Toolbar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._linkPopover = null;\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n this._statefulButtons = [];\n this._savedLinkRange = null;\n this._tableToolsSep = null;\n this._tableRowBtn = null;\n this._tableColBtn = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-block-toolbar' });\n this._linkPopover = this._createLinkPopover();\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n return this.el;\n }\n\n show(blockId) {\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) return this.hide();\n const getActiveBlockId = () => this.editor._selectedBlockId || blockId;\n\n this.el.innerHTML = '';\n this.el.classList.add('fe-visible');\n this._statefulButtons = [];\n\n // Drag handle\n this._addBtn(icons.dragHandle, 'Drag', null, 'fe-tb-drag');\n\n this._addSep();\n\n // Move buttons\n this._addBtn(icons.arrowUp, 'Move up', () => this.editor.blockManager.moveBlock(blockId, -1));\n this._addBtn(icons.arrowDown, 'Move down', () => this.editor.blockManager.moveBlock(blockId, 1));\n\n this._addSep();\n\n // Type-specific tools\n const type = block.type;\n const textTypes = ['paragraph', 'heading', 'heading-3', 'heading-4', 'quote', 'pullquote', 'list', 'ordered-list'];\n const htmlEditableTypes = [...textTypes, 'code', 'html'];\n\n if (textTypes.includes(type)) {\n // Block type selector\n const select = el('select', { className: 'fe-tb-select' });\n const options = [\n { value: 'paragraph', label: 'Paragraph' },\n { value: 'heading', label: 'Heading 2' },\n { value: 'heading-3', label: 'Heading 3' },\n { value: 'heading-4', label: 'Heading 4' },\n { value: 'quote', label: 'Quote' },\n { value: 'list', label: 'Bullet List' },\n { value: 'ordered-list', label: 'Numbered List' },\n { value: 'code', label: 'Code' },\n ];\n options.forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n if (opt.value === type) o.selected = true;\n select.appendChild(o);\n });\n select.addEventListener('change', () => {\n const value = select.value;\n const blockNow = this.editor.blockManager.getBlock(blockId);\n if (!blockNow) return;\n\n const ensureParagraphContext = () => {\n if (blockNow.type !== 'paragraph') {\n this.editor.blockManager.changeBlockType(blockId, 'paragraph');\n this.editor.render();\n }\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.focus();\n return contentEl;\n };\n\n if (value === 'paragraph' || value === 'heading' || value === 'heading-3' || value === 'heading-4' || value === 'quote') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n const tag = value === 'paragraph'\n ? 'P'\n : value === 'heading'\n ? 'H2'\n : value === 'heading-3'\n ? 'H3'\n : value === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (value === 'list' || value === 'ordered-list') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n document.execCommand(value === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n this.editor.blockManager.changeBlockType(blockId, value);\n this.editor.render();\n this.editor.focusBlock(blockId);\n });\n this.el.appendChild(select);\n\n this._addSep();\n\n // Font size\n const fontSizeSelect = el('select', { className: 'fe-tb-select', title: 'Font size' });\n [\n { value: '', label: 'Size' },\n { value: '13', label: '13px' },\n { value: '16', label: '16px' },\n { value: '20', label: '20px' },\n { value: '28', label: '28px' },\n { value: '36', label: '36px' },\n ].forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n fontSizeSelect.appendChild(o);\n });\n fontSizeSelect.addEventListener('change', () => {\n if (!fontSizeSelect.value) return;\n this._applyFontSize(fontSizeSelect.value);\n this._syncFontSizeSelect();\n });\n this.el.appendChild(fontSizeSelect);\n this._fontSizeSelect = fontSizeSelect;\n this._bindFontSizeTracking();\n this._syncFontSizeSelect();\n\n this._addSep();\n\n // Formatting\n this._addStatefulBtn('bold', icons.bold, 'Bold (Ctrl+B)', () => this._exec('bold'));\n this._addStatefulBtn('italic', icons.italic, 'Italic (Ctrl+I)', () => this._exec('italic'));\n this._addStatefulBtn('underline', icons.underline, 'Underline (Ctrl+U)', () => this._exec('underline'));\n this._addStatefulBtn('strikeThrough', icons.strikethrough, 'Strikethrough', () => this._exec('strikeThrough'));\n this._addBtn(icons.inlineCode, 'Inline Code', () => this._wrapInlineCode());\n this._addStatefulBtn('link', icons.link, 'Link (Ctrl+K)', () => this._showLinkPopover());\n\n this._addSep();\n\n // Alignment\n this._addBtn(icons.alignLeft, 'Align Left', () => this._exec('justifyLeft'));\n this._addBtn(icons.alignCenter, 'Align Center', () => this._exec('justifyCenter'));\n this._addBtn(icons.alignRight, 'Align Right', () => this._exec('justifyRight'));\n\n this._tableToolsSep = this._addSep();\n this._tableRowBtn = this._addTextBtn('+Row', 'Add table row', () => this._addTableRow());\n this._tableColBtn = this._addTextBtn('+Col', 'Add table column', () => this._addTableColumn());\n }\n\n if (htmlEditableTypes.includes(type)) {\n this._addSep();\n this._addBtn(\n icons.html,\n type === 'html' ? 'Switch to normal text mode' : 'Switch to HTML mode',\n () => this.editor.toggleBlockHtmlMode(getActiveBlockId()),\n type === 'html' ? 'active' : ''\n );\n }\n\n this._syncStatefulButtons();\n\n this._addSep();\n\n // Duplicate & Delete\n this._addBtn(icons.file, 'Duplicate', () => {\n const clone = this.editor.blockManager.duplicateBlock(getActiveBlockId());\n if (clone) this.editor.render();\n });\n this._addBtn(icons.trash, 'Delete', () => {\n const activeId = getActiveBlockId();\n const removed = this.editor.blockManager.removeBlock(activeId);\n if (removed) {\n this.editor.render();\n return;\n }\n\n // If only one block remains, make delete behave like \"clear block\".\n const blockToClear = this.editor.blockManager.getBlock(activeId);\n if (!blockToClear) return;\n blockToClear.type = 'paragraph';\n blockToClear.content = '';\n blockToClear.attrs = {};\n this.editor.render();\n this.editor.focusBlock(activeId);\n }, 'fe-tb-btn-danger');\n }\n\n hide() {\n if (this.el) this.el.classList.remove('fe-visible');\n this._hideLinkPopover();\n this._unbindFontSizeTracking();\n }\n\n /* ---- Private ---- */\n\n _addBtn(iconHTML, title, onClick, extraClass = '') {\n const btn = el('button', {\n className: `fe-tb-btn ${extraClass}`.trim(),\n type: 'button',\n innerHTML: iconHTML,\n title,\n });\n btn.addEventListener('mousedown', (e) => {\n // Preserve current editor selection for rich-text commands/popovers.\n e.preventDefault();\n e.stopPropagation();\n });\n if (onClick) btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); onClick(); });\n this.el.appendChild(btn);\n return btn;\n }\n\n _addStatefulBtn(command, iconHTML, title, onClick) {\n const btn = this._addBtn(iconHTML, title, onClick);\n this._statefulButtons.push({ command, btn });\n return btn;\n }\n\n _addSep() {\n const sep = el('span', { className: 'fe-tb-sep' });\n this.el.appendChild(sep);\n return sep;\n }\n\n _addTextBtn(label, title, onClick) {\n const btn = el('button', {\n className: 'fe-tb-text-btn',\n type: 'button',\n title,\n innerHTML: label,\n });\n btn.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n });\n this.el.appendChild(btn);\n return btn;\n }\n\n _exec(cmd) {\n document.execCommand(cmd, false, null);\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n }\n\n _wrapInlineCode() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n const code = document.createElement('code');\n code.className = 'fe-inline-code';\n range.surroundContents(code);\n this.editor._syncCurrentBlockContent();\n }\n\n _applyFontSize(px) {\n const size = Number(px);\n if (!Number.isFinite(size)) return;\n\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n\n if (range.collapsed) {\n // Apply style for text typed from the current caret onward only.\n const marker = document.createElement('span');\n marker.style.fontSize = `${size}px`;\n marker.appendChild(document.createTextNode('\\u200B'));\n range.insertNode(marker);\n\n const nextRange = document.createRange();\n nextRange.setStart(marker.firstChild, 1);\n nextRange.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n const span = document.createElement('span');\n span.style.fontSize = `${size}px`;\n span.appendChild(range.extractContents());\n range.insertNode(span);\n\n const nextRange = document.createRange();\n nextRange.selectNodeContents(span);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n this.editor._syncCurrentBlockContent();\n }\n\n _bindFontSizeTracking() {\n if (!this._fontSizeSelect || this._onSelectionChange) return;\n this._onSelectionChange = () => {\n this._syncFontSizeSelect();\n this._syncStatefulButtons();\n };\n document.addEventListener('selectionchange', this._onSelectionChange);\n }\n\n _unbindFontSizeTracking() {\n if (!this._onSelectionChange) return;\n document.removeEventListener('selectionchange', this._onSelectionChange);\n this._onSelectionChange = null;\n }\n\n _syncFontSizeSelect() {\n if (!this._fontSizeSelect) return;\n const px = this._currentSelectionFontSizePx();\n if (!px) {\n this._fontSizeSelect.value = '';\n return;\n }\n const snapped = _closestFontSize(px, [13, 16, 20, 28, 36]);\n this._fontSizeSelect.value = String(snapped);\n }\n\n _currentSelectionFontSizePx() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const node = sel.focusNode;\n if (!node) return null;\n const elNode = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!elNode) return null;\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper || !wrapper.contains(elNode)) return null;\n const raw = window.getComputedStyle(elNode).fontSize;\n const px = Number.parseFloat(raw || '');\n return Number.isFinite(px) ? px : null;\n }\n\n _createLinkPopover() {\n const pop = el('div', { className: 'fe-link-popover' });\n const input = el('input', { type: 'text', placeholder: 'Paste URL or search...', className: 'fe-link-input' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary fe-btn-sm',\n innerHTML: 'Apply',\n });\n const removeBtn = el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: 'Remove',\n });\n\n applyBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n if (input.value) {\n document.execCommand('createLink', false, input.value);\n // Style links\n const wrapper = this.editor._getSelectedBlockEl();\n if (wrapper) {\n wrapper.querySelectorAll('a').forEach((a) => {\n a.classList.add('fe-link');\n a.target = '_blank';\n a.rel = 'noopener';\n });\n }\n }\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n removeBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n document.execCommand('unlink', false, null);\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (e.key === 'Escape') this._hideLinkPopover();\n });\n\n pop.appendChild(input);\n pop.appendChild(applyBtn);\n pop.appendChild(removeBtn);\n return pop;\n }\n\n _showLinkPopover() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n this._savedLinkRange = range.cloneRange();\n const rect = range.getBoundingClientRect();\n const wrapper = this.el.parentElement;\n if (!wrapper) return;\n\n if (!this._linkPopover.parentElement) {\n wrapper.appendChild(this._linkPopover);\n }\n\n this._linkPopover.style.top = (rect.bottom - wrapper.getBoundingClientRect().top + 6) + 'px';\n this._linkPopover.style.left = '0px';\n this._linkPopover.classList.add('fe-open');\n\n // Pre-fill if there's an existing link\n const anchor = sel.anchorNode?.parentElement?.closest('a');\n const input = this._linkPopover.querySelector('input');\n input.value = anchor ? anchor.href : '';\n setTimeout(() => input.focus(), 10);\n }\n\n _hideLinkPopover() {\n if (this._linkPopover) this._linkPopover.classList.remove('fe-open');\n }\n\n _getCurrentTableContext() {\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper) return null;\n const contentEl = wrapper.querySelector('.fe-block-content');\n if (!contentEl) return null;\n\n const sel = window.getSelection();\n let cell = null;\n if (sel && sel.rangeCount > 0) {\n let node = sel.anchorNode;\n if (node && node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (node && typeof node.closest === 'function') {\n const maybeCell = node.closest('td,th');\n if (maybeCell && contentEl.contains(maybeCell)) cell = maybeCell;\n }\n }\n\n const table = cell ? cell.closest('table') : contentEl.querySelector('table');\n if (!table) return null;\n if (!cell) cell = table.querySelector('td,th');\n if (!cell) return null;\n return { table, cell };\n }\n\n _addTableRow() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const rowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n if (currentRow.nextSibling) currentRow.parentNode.insertBefore(newRow, currentRow.nextSibling);\n else currentRow.parentNode.appendChild(newRow);\n\n const range = document.createRange();\n range.selectNodeContents(newRow.querySelector('td'));\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n this.editor._syncCurrentBlockContent();\n }\n\n _addTableColumn() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const idx = Array.from(currentRow.querySelectorAll('th,td')).indexOf(cell);\n if (idx < 0) return;\n\n const rows = Array.from(table.querySelectorAll('tr'));\n rows.forEach((row) => {\n const cells = Array.from(row.querySelectorAll('th,td'));\n const ref = cells[Math.min(idx, cells.length - 1)];\n const newCell = document.createElement(ref && ref.tagName.toLowerCase() === 'th' ? 'th' : 'td');\n newCell.innerHTML = '<br>';\n if (ref && ref.nextSibling) row.insertBefore(newCell, ref.nextSibling);\n else row.appendChild(newCell);\n });\n\n const targetRowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const focusCell = targetRowCells[Math.min(idx + 1, targetRowCells.length - 1)];\n if (focusCell) {\n const range = document.createRange();\n range.selectNodeContents(focusCell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n this.editor._syncCurrentBlockContent();\n }\n\n _restoreSavedLinkRange() {\n if (!this._savedLinkRange) return;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedLinkRange);\n }\n\n _syncStatefulButtons() {\n const wrapper = this.editor._getSelectedBlockEl();\n const sel = window.getSelection();\n const anchor = sel?.anchorNode?.parentElement?.closest('a');\n const hasSelectionInEditor =\n wrapper &&\n sel &&\n sel.rangeCount > 0 &&\n wrapper.contains(sel.anchorNode);\n\n this._statefulButtons.forEach(({ command, btn }) => {\n let active = false;\n if (hasSelectionInEditor) {\n if (command === 'link') {\n active = Boolean(anchor && wrapper.contains(anchor));\n } else {\n try {\n active = document.queryCommandState(command);\n } catch {\n active = false;\n }\n }\n }\n btn.classList.toggle('active', Boolean(active));\n });\n\n const inTable = this._isSelectionInTable(wrapper);\n const tableDisplay = inTable ? '' : 'none';\n if (this._tableToolsSep) this._tableToolsSep.style.display = tableDisplay;\n if (this._tableRowBtn) this._tableRowBtn.style.display = tableDisplay;\n if (this._tableColBtn) this._tableColBtn.style.display = tableDisplay;\n }\n\n _isSelectionInTable(wrapper) {\n if (!wrapper) return false;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let node = sel.anchorNode;\n if (!node) return false;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return false;\n const table = node.closest('table');\n return Boolean(table && wrapper.contains(table));\n }\n}\n\nfunction _closestFontSize(value, sizes) {\n let best = sizes[0];\n let bestDelta = Math.abs(value - best);\n for (let i = 1; i < sizes.length; i++) {\n const delta = Math.abs(value - sizes[i]);\n if (delta < bestDelta) {\n best = sizes[i];\n bestDelta = delta;\n }\n }\n return best;\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { CATEGORIES, getBlocksByCategory, searchBlocks } from '../blocks/registry.js';\n\n/**\n * Side panel for browsing and inserting block types.\n */\nexport class InserterPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._searchInput = null;\n this._listEl = null;\n this._anchorEl = null;\n this._onDocMouseDown = null;\n this._onDocKeyDown = null;\n this._savedRange = null;\n this._mediaModal = null;\n this._mediaModalCard = null;\n this._mediaModalTitle = null;\n this._mediaModalBody = null;\n this._mediaModalResolver = null;\n this._forceNewBlock = false;\n }\n\n create() {\n this.el = el('div', { className: 'fe-inserter-panel' });\n\n // Header\n const header = el('div', { className: 'fe-inserter-header' });\n header.appendChild(el('h3', {}, ['Blocks']));\n const closeBtn = el('button', {\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this.close(),\n });\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n // Search\n this._searchInput = el('input', {\n type: 'text',\n className: 'fe-inserter-search',\n placeholder: 'Search blocks...',\n });\n this._searchInput.addEventListener('input', () => this._renderList());\n this.el.appendChild(this._searchInput);\n\n // List\n this._listEl = el('div', { className: 'fe-inserter-list' });\n this.el.appendChild(this._listEl);\n\n this._renderList();\n this._createMediaModal();\n return this.el;\n }\n\n open(anchorEl = null, options = {}) {\n this._anchorEl = anchorEl || this._anchorEl;\n this._forceNewBlock = Boolean(options.forceNewBlock);\n this._savedRange = this._captureSelectionRange();\n this._positionNearAnchor();\n this.el.classList.add('fe-open');\n this._searchInput.value = '';\n this._renderList();\n this._bindGlobalCloseHandlers();\n setTimeout(() => this._searchInput.focus(), 20);\n }\n\n close() {\n this.el.classList.remove('fe-open');\n this._forceNewBlock = false;\n this._unbindGlobalCloseHandlers();\n }\n\n toggle(anchorEl = null, options = {}) {\n if (anchorEl) this._anchorEl = anchorEl;\n this.el.classList.contains('fe-open') ? this.close() : this.open(anchorEl, options);\n }\n\n isOpen() {\n return this.el.classList.contains('fe-open');\n }\n\n _renderList() {\n this._listEl.innerHTML = '';\n const query = this._searchInput?.value?.trim() || '';\n\n if (query) {\n const results = searchBlocks(query);\n if (results.length === 0) {\n this._listEl.appendChild(el('p', { className: 'fe-inserter-empty' }, ['No blocks found.']));\n return;\n }\n results.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n } else {\n for (const cat of CATEGORIES) {\n const blocks = getBlocksByCategory(cat.id);\n if (blocks.length === 0) continue;\n this._listEl.appendChild(el('div', { className: 'fe-inserter-category' }, [cat.label]));\n blocks.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n }\n }\n }\n\n _createBlockItem(blockDef) {\n const item = el('div', { className: 'fe-inserter-item' });\n item.appendChild(el('div', { className: 'fe-inserter-item-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-inserter-item-info' });\n info.appendChild(el('h4', {}, [blockDef.label]));\n info.appendChild(el('p', {}, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => {\n this._insertFromPopover(blockDef.type);\n this.close();\n });\n\n return item;\n }\n\n _positionNearAnchor() {\n if (!this.el || !this._anchorEl) return;\n const rect = this._anchorEl.getBoundingClientRect();\n const gap = 8;\n const desiredLeft = Math.max(8, Math.min(window.innerWidth - 368, rect.left));\n const desiredTop = Math.max(8, Math.min(window.innerHeight - 520, rect.bottom + gap));\n this.el.style.left = `${desiredLeft}px`;\n this.el.style.top = `${desiredTop}px`;\n }\n\n _bindGlobalCloseHandlers() {\n this._onDocMouseDown = (e) => {\n if (!this.el?.classList.contains('fe-open')) return;\n if (this.el.contains(e.target)) return;\n if (this._anchorEl && this._anchorEl.contains(e.target)) return;\n this.close();\n };\n this._onDocKeyDown = (e) => {\n if (e.key === 'Escape') this.close();\n };\n document.addEventListener('mousedown', this._onDocMouseDown);\n document.addEventListener('keydown', this._onDocKeyDown);\n window.addEventListener('resize', () => this._positionNearAnchor(), { once: true });\n }\n\n _unbindGlobalCloseHandlers() {\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown);\n this._onDocMouseDown = null;\n }\n if (this._onDocKeyDown) {\n document.removeEventListener('keydown', this._onDocKeyDown);\n this._onDocKeyDown = null;\n }\n }\n\n _captureSelectionRange() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n const container = range.commonAncestorContainer;\n if (!this.editor.rootEl.contains(container)) return null;\n return range.cloneRange();\n }\n\n _restoreSelectionRange() {\n if (!this._savedRange) return false;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange);\n return true;\n }\n\n async _insertFromPopover(type) {\n if (this._forceNewBlock) {\n const selectedId = this.editor._selectedBlockId;\n const block = this.editor.blockManager.addBlock(type, {}, selectedId || null);\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n const selectedId = this.editor._selectedBlockId;\n const selectedBlock = selectedId ? this.editor.blockManager.getBlock(selectedId) : null;\n const canInline =\n selectedBlock &&\n selectedBlock.type !== 'code' &&\n selectedBlock.type !== 'html' &&\n selectedBlock.type !== 'image' &&\n selectedBlock.type !== 'gallery' &&\n selectedBlock.type !== 'video' &&\n selectedBlock.type !== 'audio' &&\n selectedBlock.type !== 'file';\n\n if (!canInline) {\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n return;\n }\n\n this._restoreSelectionRange();\n const contentEl = this.editor._getBlockContentEl(selectedId);\n if (contentEl) contentEl.focus();\n\n if (type === 'paragraph' || type === 'heading' || type === 'heading-3' || type === 'heading-4' || type === 'quote') {\n const tag = type === 'paragraph'\n ? 'P'\n : type === 'heading'\n ? 'H2'\n : type === 'heading-3'\n ? 'H3'\n : type === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'list' || type === 'ordered-list') {\n document.execCommand(type === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'image') {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (!files.length) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n const src = result.remoteUrl || result.localUrl;\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n this.editor._syncCurrentBlockContent();\n }\n return;\n }\n\n if (type === 'video' || type === 'audio') {\n const source = await this._chooseMediaSource(type);\n if (!source) return;\n\n if (source === 'url') {\n const url = await this._promptForMediaUrl(type);\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${trimmed}\"></video><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${trimmed}\"></audio><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n }\n\n if (type === 'video' || type === 'audio' || type === 'file') {\n const accept = type === 'video' ? 'video/*' : type === 'audio' ? 'audio/*' : '*/*';\n const files = await this.editor.mediaUploader.openFilePicker(accept);\n if (!files.length) return;\n const file = files[0];\n const result = await this.editor.mediaUploader.processFile(file);\n if (result.error) {\n if (typeof this.editor._showToast === 'function') this.editor._showToast(result.error);\n return;\n }\n const src = result.remoteUrl || result.localUrl;\n if (!src) return;\n\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`);\n } else if (type === 'audio') {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<p><a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${file.name || 'Download file'}</a></p><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'embed') {\n const url = window.prompt('Paste embed URL');\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n document.execCommand('insertHTML', false, `<p><a href=\"${trimmed}\" target=\"_blank\" rel=\"noopener\">${trimmed}</a></p><p><br></p>`);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n }\n\n async _chooseMediaSource(type) {\n if (typeof this.editor.options.onChooseMediaSource === 'function') {\n const selected = await this.editor.options.onChooseMediaSource(type);\n if (selected === 'url' || selected === 'upload') return selected;\n }\n return this._openMediaSourceModal(type);\n }\n\n _createMediaModal() {\n const overlay = el('div', { className: 'fe-media-modal-overlay' });\n const card = el('div', { className: 'fe-media-modal-card' });\n const title = el('h3', { className: 'fe-media-modal-title' }, ['Insert media']);\n const body = el('div', { className: 'fe-media-modal-body' });\n\n card.appendChild(title);\n card.appendChild(body);\n overlay.appendChild(card);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeMediaModal(null);\n });\n\n this.editor.rootEl.appendChild(overlay);\n this._mediaModal = overlay;\n this._mediaModalCard = card;\n this._mediaModalTitle = title;\n this._mediaModalBody = body;\n }\n\n _openMediaSourceModal(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `Insert ${type}`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Choose how you want to add media']);\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Upload File',\n onClick: () => this._closeMediaModal('upload'),\n });\n const urlBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n type: 'button',\n innerHTML: 'Use URL',\n onClick: () => this._closeMediaModal('url'),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n actions.appendChild(uploadBtn);\n actions.appendChild(urlBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(actions);\n\n this._mediaModal.classList.add('fe-open');\n });\n }\n\n _promptForMediaUrl(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `${type} URL`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Paste a direct media URL']);\n const input = el('input', {\n type: 'url',\n className: 'fe-media-modal-input',\n placeholder: `https://example.com/${type}.mp4`,\n });\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Insert',\n onClick: () => this._closeMediaModal(input.value || null),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._closeMediaModal(input.value || null);\n }\n if (e.key === 'Escape') this._closeMediaModal(null);\n });\n\n actions.appendChild(applyBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(input);\n this._mediaModalBody.appendChild(actions);\n this._mediaModal.classList.add('fe-open');\n setTimeout(() => input.focus(), 0);\n });\n }\n\n _closeMediaModal(value) {\n if (!this._mediaModal) return;\n this._mediaModal.classList.remove('fe-open');\n const resolver = this._mediaModalResolver;\n this._mediaModalResolver = null;\n if (resolver) resolver(value);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Right-hand settings panel with Post and Block tabs.\n */\nexport class SettingsPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._activeTab = 'post';\n this._postTab = null;\n this._blockTab = null;\n this._tagInput = null;\n this._tags = [];\n this._categories = ['Uncategorized', 'Technology', 'Design', 'Business', 'Lifestyle'];\n this._featuredImage = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-settings-panel' });\n\n // Tabs\n const tabs = el('div', { className: 'fe-panel-tabs' });\n this._postTabBtn = el('button', { className: 'fe-panel-tab fe-active' }, ['Post']);\n this._blockTabBtn = el('button', { className: 'fe-panel-tab' }, ['Block']);\n this._postTabBtn.addEventListener('click', () => this._switchTab('post'));\n this._blockTabBtn.addEventListener('click', () => this._switchTab('block'));\n tabs.appendChild(this._postTabBtn);\n tabs.appendChild(this._blockTabBtn);\n this.el.appendChild(tabs);\n\n // Post tab content\n this._postTab = el('div', { className: 'fe-tab-content' });\n this._buildPostTab();\n this.el.appendChild(this._postTab);\n\n // Block tab content\n this._blockTab = el('div', { className: 'fe-tab-content', style: { display: 'none' } });\n this._buildBlockTab();\n this.el.appendChild(this._blockTab);\n\n return this.el;\n }\n\n open() { this.el.classList.add('fe-open'); }\n close() { this.el.classList.remove('fe-open'); }\n toggle() { this.el.classList.contains('fe-open') ? this.close() : this.open(); }\n isOpen() { return this.el.classList.contains('fe-open'); }\n\n updateBlockSettings(blockId) {\n this._blockSettingsContent.innerHTML = '';\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) {\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n return;\n }\n\n // Typography\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Typography']));\n\n // Font size\n section.appendChild(el('label', {}, ['Font size']));\n const fontSelect = el('select', { className: 'fe-input' });\n [{ v: '', l: 'Default' }, { v: '13px', l: 'Small' }, { v: '16px', l: 'Medium' }, { v: '20px', l: 'Large' }, { v: '28px', l: 'Extra Large' }, { v: '36px', l: 'Huge' }]\n .forEach(({ v, l }) => fontSelect.appendChild(el('option', { value: v }, [l])));\n fontSelect.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.fontSize = fontSelect.value;\n });\n section.appendChild(fontSelect);\n\n // Line height\n section.appendChild(el('label', {}, ['Line height']));\n const lhInput = el('input', { type: 'text', className: 'fe-input', placeholder: '1.7' });\n lhInput.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl && lhInput.value) contentEl.style.lineHeight = lhInput.value;\n });\n section.appendChild(lhInput);\n\n this._blockSettingsContent.appendChild(section);\n\n // Color\n const colorSection = el('div', { className: 'fe-panel-section' });\n colorSection.appendChild(el('h3', { className: 'fe-section-title' }, ['Color']));\n\n // Text colors\n colorSection.appendChild(el('label', {}, ['Text color']));\n const textColors = el('div', { className: 'fe-color-grid' });\n ['#1e1e1e', '#cf2e2e', '#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#0693e3', '#9b51e0'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.color = c;\n });\n textColors.appendChild(swatch);\n });\n colorSection.appendChild(textColors);\n\n // BG colors\n colorSection.appendChild(el('label', {}, ['Background color']));\n const bgColors = el('div', { className: 'fe-color-grid' });\n ['transparent', '#fcf0f0', '#fef8ee', '#fefce8', '#edf7f2', '#eef6fc', '#f3eafa', '#f0f0f1'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c === 'transparent' ? '#fff' : c, border: c === 'transparent' ? '2px solid #ddd' : 'none' } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.background = c;\n });\n bgColors.appendChild(swatch);\n });\n colorSection.appendChild(bgColors);\n\n this._blockSettingsContent.appendChild(colorSection);\n }\n\n _switchTab(tab) {\n this._activeTab = tab;\n this._postTabBtn.classList.toggle('fe-active', tab === 'post');\n this._blockTabBtn.classList.toggle('fe-active', tab === 'block');\n this._postTab.style.display = tab === 'post' ? 'block' : 'none';\n this._blockTab.style.display = tab === 'block' ? 'block' : 'none';\n }\n\n _buildPostTab() {\n // Summary\n const summary = this._section('Summary');\n summary.appendChild(this._field('Visibility', 'select', ['Public', 'Private', 'Password Protected']));\n summary.appendChild(this._field('Publish', 'select', ['Immediately', 'Schedule']));\n summary.appendChild(this._field('URL Slug', 'text', null, 'fe-url-slug'));\n summary.appendChild(this._field('Author', 'select', ['Admin', 'Editor', 'Author']));\n this._postTab.appendChild(summary);\n\n // Categories\n const cats = this._section('Categories');\n const catList = el('div', { className: 'fe-category-list' });\n this._categories.forEach((cat) => {\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox' }));\n label.appendChild(document.createTextNode(' ' + cat));\n catList.appendChild(label);\n });\n cats.appendChild(catList);\n const addCat = el('a', { href: '#', className: 'fe-add-link' }, ['+ Add New Category']);\n addCat.addEventListener('click', (e) => {\n e.preventDefault();\n const name = prompt('Category name:');\n if (name) {\n this._categories.push(name);\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox', checked: true }));\n label.appendChild(document.createTextNode(' ' + name));\n catList.appendChild(label);\n }\n });\n cats.appendChild(addCat);\n this._postTab.appendChild(cats);\n\n // Tags\n const tags = this._section('Tags');\n const tagWrapper = el('div', { className: 'fe-tag-input-wrapper' });\n const tagInput = el('input', { type: 'text', placeholder: 'Add tag...' });\n tagInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault();\n const val = tagInput.value.replace(',', '').trim();\n if (!val) return;\n this._tags.push(val);\n const tag = el('span', { className: 'fe-tag' });\n tag.appendChild(document.createTextNode(val + ' '));\n const remove = el('span', { className: 'fe-tag-remove', innerHTML: '×' });\n remove.addEventListener('click', () => {\n this._tags = this._tags.filter((t) => t !== val);\n tag.remove();\n });\n tag.appendChild(remove);\n tagWrapper.insertBefore(tag, tagInput);\n tagInput.value = '';\n }\n });\n tagWrapper.appendChild(tagInput);\n tagWrapper.addEventListener('click', () => tagInput.focus());\n tags.appendChild(tagWrapper);\n tags.appendChild(el('p', { className: 'fe-hint' }, ['Separate with commas or Enter key']));\n this._postTab.appendChild(tags);\n\n // Featured Image\n const fi = this._section('Featured Image');\n const fiArea = el('div', { className: 'fe-featured-image-area' });\n fiArea.appendChild(el('p', {}, ['Set featured image']));\n const fiInput = el('input', { type: 'file', accept: 'image/*', style: { display: 'none' } });\n fiInput.addEventListener('change', (e) => {\n const file = e.target.files[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (ev) => {\n fiArea.innerHTML = '';\n const img = el('img', { src: ev.target.result });\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n fiArea.appendChild(img);\n this._featuredImage = ev.target.result;\n this.editor.emit('featuredImage:change', this._featuredImage);\n };\n reader.readAsDataURL(file);\n });\n fiArea.addEventListener('click', () => fiInput.click());\n fi.appendChild(fiArea);\n fi.appendChild(fiInput);\n this._postTab.appendChild(fi);\n\n // Excerpt\n const exc = this._section('Excerpt');\n exc.appendChild(el('textarea', { className: 'fe-input fe-textarea', placeholder: 'Write an excerpt (optional)' }));\n this._postTab.appendChild(exc);\n\n // Discussion\n const disc = this._section('Discussion');\n disc.appendChild(this._toggle('Allow comments', true));\n disc.appendChild(this._toggle('Allow pingbacks', false));\n this._postTab.appendChild(disc);\n }\n\n _buildBlockTab() {\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Block Settings']));\n this._blockSettingsContent = el('div');\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n section.appendChild(this._blockSettingsContent);\n this._blockTab.appendChild(section);\n }\n\n _section(title) {\n const s = el('div', { className: 'fe-panel-section' });\n s.appendChild(el('h3', { className: 'fe-section-title' }, [title]));\n return s;\n }\n\n _field(label, type, options, id) {\n const frag = document.createDocumentFragment();\n frag.appendChild(el('label', {}, [label]));\n if (type === 'select') {\n const select = el('select', { className: 'fe-input' });\n if (id) select.id = id;\n (options || []).forEach((o) => select.appendChild(el('option', {}, [o])));\n frag.appendChild(select);\n } else {\n const input = el('input', { type, className: 'fe-input', placeholder: label.toLowerCase() });\n if (id) input.id = id;\n frag.appendChild(input);\n }\n return frag;\n }\n\n _toggle(label, defaultOn) {\n const row = el('div', { className: 'fe-toggle-row' });\n row.appendChild(el('label', {}, [label]));\n const btn = el('button', { className: `fe-toggle-switch ${defaultOn ? 'fe-on' : ''}` });\n btn.addEventListener('click', () => btn.classList.toggle('fe-on'));\n row.appendChild(btn);\n return row;\n }\n}\n","import { el } from '../utils/dom.js';\nimport { searchBlocks, BLOCK_TYPES } from '../blocks/registry.js';\n\n/**\n * Inline slash-command menu that appears when user types \"/\".\n */\nexport class SlashMenu {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._visible = false;\n this._highlightIndex = 0;\n this._items = [];\n this._targetBlock = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-slash-menu' });\n this._boundDocClick = (e) => {\n if (!e.target.closest('.fe-slash-menu')) this.close();\n };\n document.addEventListener('click', this._boundDocClick);\n return this.el;\n }\n\n /** Remove global listeners. Called by editor.destroy(). */\n destroy() {\n if (this._boundDocClick) {\n document.removeEventListener('click', this._boundDocClick);\n this._boundDocClick = null;\n }\n }\n\n open(block, rect) {\n this._targetBlock = block;\n this._visible = true;\n this._highlightIndex = 0;\n this.el.classList.add('fe-open');\n\n // Position near the caret\n const editorRect = this.editor.el.getBoundingClientRect();\n this.el.style.top = (rect.bottom - editorRect.top + 4) + 'px';\n this.el.style.left = (rect.left - editorRect.left) + 'px';\n\n this._filter('');\n }\n\n close() {\n this._visible = false;\n this._targetBlock = null;\n this.el.classList.remove('fe-open');\n }\n\n isOpen() {\n return this._visible;\n }\n\n filter(query) {\n this._filter(query);\n }\n\n handleKeydown(e) {\n if (!this._visible) return false;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._navigate(1);\n return true;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n this._navigate(-1);\n return true;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n if (visible[this._highlightIndex]) {\n this._selectItem(visible[this._highlightIndex].type);\n }\n return true;\n }\n if (e.key === 'Escape') {\n this.close();\n return true;\n }\n return false;\n }\n\n _filter(query) {\n this.el.innerHTML = '';\n this._items = [];\n\n const allBlocks = query ? searchBlocks(query) : Object.entries(BLOCK_TYPES).map(([type, def]) => ({ type, ...def }));\n\n allBlocks.forEach((blockDef, i) => {\n const item = el('div', { className: `fe-slash-item ${i === 0 ? 'fe-highlighted' : ''}` });\n item.appendChild(el('div', { className: 'fe-slash-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-slash-info' });\n info.appendChild(el('div', { className: 'fe-slash-label' }, [blockDef.label]));\n info.appendChild(el('div', { className: 'fe-slash-desc' }, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => this._selectItem(blockDef.type));\n item.addEventListener('mouseenter', () => {\n this.el.querySelectorAll('.fe-slash-item').forEach((el) => el.classList.remove('fe-highlighted'));\n item.classList.add('fe-highlighted');\n });\n\n this.el.appendChild(item);\n this._items.push({ el: item, type: blockDef.type });\n });\n\n if (this._items.length === 0) {\n this.el.appendChild(el('div', { className: 'fe-slash-empty' }, ['No blocks found']));\n }\n\n this._highlightIndex = 0;\n }\n\n _navigate(dir) {\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n visible.forEach((i) => i.el.classList.remove('fe-highlighted'));\n this._highlightIndex = Math.max(0, Math.min(visible.length - 1, this._highlightIndex + dir));\n if (visible[this._highlightIndex]) {\n visible[this._highlightIndex].el.classList.add('fe-highlighted');\n visible[this._highlightIndex].el.scrollIntoView({ block: 'nearest' });\n }\n }\n\n _selectItem(type) {\n if (!this._targetBlock) return;\n const block = this._targetBlock;\n const inserted = this.editor.insertSingleBlockType(type);\n if (inserted) {\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n // Change the block type and clear content\n this.editor.blockManager.changeBlockType(block.id, type);\n block.content = '';\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Bottom status bar showing word count, character count, block count.\n */\nexport class StatusBar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._wordEl = null;\n this._charEl = null;\n this._blockEl = null;\n this._savedEl = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-status-bar' });\n this._wordEl = el('span', {}, ['Words: 0']);\n this._charEl = el('span', {}, ['Characters: 0']);\n this._blockEl = el('span', {}, ['Blocks: 0']);\n this._savedEl = el('span', { className: 'fe-status-right' });\n\n this.el.appendChild(this._wordEl);\n this.el.appendChild(this._charEl);\n this.el.appendChild(this._blockEl);\n this.el.appendChild(this._savedEl);\n\n return this.el;\n }\n\n update() {\n const bm = this.editor.blockManager;\n const titleText = this.editor._titleEl ? this.editor._titleEl.value : '';\n const titleWords = titleText.trim().split(/\\s+/).filter((w) => w.length).length;\n const words = bm.getWordCount() + titleWords;\n const chars = bm.getCharCount() + titleText.replace(/\\s/g, '').length;\n\n this._wordEl.textContent = `Words: ${words}`;\n this._charEl.textContent = `Characters: ${chars}`;\n this._blockEl.textContent = `Blocks: ${bm.blocks.length}`;\n }\n\n setSaved(text) {\n this._savedEl.textContent = text;\n }\n}\n","import { EventEmitter } from './utils/EventEmitter.js';\nimport { el, placeCaretAtEnd, placeCaretAtStart, getCaretRect } from './utils/dom.js';\nimport { icons } from './utils/icons.js';\nimport { BlockManager } from './core/BlockManager.js';\nimport { MediaUploader } from './core/MediaUploader.js';\nimport { DragDrop } from './core/DragDrop.js';\nimport { BlockRenderer } from './blocks/BlockRenderer.js';\nimport { Header } from './ui/Header.js';\nimport { Toolbar } from './ui/Toolbar.js';\nimport { InserterPanel } from './ui/InserterPanel.js';\nimport { SettingsPanel } from './ui/SettingsPanel.js';\nimport { SlashMenu } from './ui/SlashMenu.js';\nimport { StatusBar } from './ui/StatusBar.js';\n\n/**\n * NBDEditor — Gutenberg-style block editor.\n *\n * Usage:\n * const editor = new NBDEditor('#app', { ... });\n */\nexport class NBDEditor extends EventEmitter {\n constructor(selector, options = {}) {\n super();\n\n this.options = {\n siteName: 'My Site',\n authorName: 'Admin',\n showStatusBar: true,\n showSettingsPanel: false,\n showHeaderActions: false,\n placeholder: 'Start writing...',\n autoSaveInterval: 30000,\n uploadHandler: null, // async (file) => { url, id }\n maxFileSize: 10 * 1024 * 1024,\n onChooseMediaSource: null, // async/sync (type: 'video'|'audio') => 'url' | 'upload'\n content: null, // initial HTML content\n onChange: null,\n onSave: null,\n onPublish: null,\n ...options,\n };\n\n // Root element\n this.rootEl = typeof selector === 'string' ? document.querySelector(selector) : selector;\n if (!this.rootEl) throw new Error(`NBDEditor: element \"${selector}\" not found.`);\n\n // Core modules\n this.blockManager = new BlockManager();\n this.mediaUploader = new MediaUploader({\n uploadHandler: this.options.uploadHandler,\n maxFileSize: this.options.maxFileSize,\n });\n\n // UI modules\n this.blockRenderer = new BlockRenderer(this);\n this.header = new Header(this);\n this.toolbar = new Toolbar(this);\n this.inserterPanel = new InserterPanel(this);\n this.settingsPanel = new SettingsPanel(this);\n this.slashMenu = new SlashMenu(this);\n this.statusBar = new StatusBar(this);\n\n // State\n this._selectedBlockId = null;\n this._titleEl = null;\n this._blocksContainer = null;\n this._autoSaveTimer = null;\n this.el = null;\n this._htmlEditorModal = null;\n this._htmlEditorTextarea = null;\n this._htmlEditorTitle = null;\n this._htmlEditorBlockId = null;\n\n // Bound handlers for cleanup\n this._boundGlobalKeydown = (e) => this._handleGlobalKeydown(e);\n\n this._init();\n }\n\n /* ===== Initialization ===== */\n\n _init() {\n this.rootEl.innerHTML = '';\n this.rootEl.className = 'fe-root';\n\n // Header\n this.rootEl.appendChild(this.header.create());\n\n // Inserter panel\n this.rootEl.appendChild(this.inserterPanel.create());\n\n // Main wrapper\n this.el = el('div', { className: 'fe-editor-main' });\n\n // Canvas\n const canvas = el('div', { className: 'fe-editor-canvas', id: 'fe-canvas' });\n const content = el('div', { className: 'fe-editor-content' });\n\n // Blocks container\n this._blocksContainer = el('div', { className: 'fe-blocks-container' });\n content.appendChild(this._blocksContainer);\n\n canvas.appendChild(content);\n this.el.appendChild(canvas);\n\n // Settings panel\n if (this.options.showSettingsPanel) {\n this.el.appendChild(this.settingsPanel.create());\n }\n\n this.rootEl.appendChild(this.el);\n\n // Slash menu (appended to editor main for positioning)\n this.el.appendChild(this.slashMenu.create());\n\n // Status bar\n if (this.options.showStatusBar) {\n this.rootEl.appendChild(this.statusBar.create());\n }\n\n // Toast element\n this._toast = el('div', { className: 'fe-toast' });\n this.rootEl.appendChild(this._toast);\n this._createHtmlEditorModal();\n\n // Load initial content or create first block\n if (typeof this.options.content === 'string') {\n this.blockManager.fromJSON([{\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content: this.options.content,\n attrs: {},\n }]);\n } else if (this.options.content) {\n this.blockManager.fromJSON(this.options.content);\n } else {\n this.blockManager.addBlock('paragraph');\n }\n this._ensureAtLeastOneBlock();\n\n this.render();\n\n // Open settings panel by default\n if (this.options.showSettingsPanel) {\n this.settingsPanel.open();\n this._updateCanvasMargin();\n }\n\n // Keyboard shortcuts\n document.addEventListener('keydown', this._boundGlobalKeydown);\n\n // Auto-save\n if (this.options.autoSaveInterval > 0) {\n this._autoSaveTimer = setInterval(() => {\n this._syncAllBlockContent();\n this.statusBar.setSaved('Auto-saved: ' + new Date().toLocaleTimeString());\n this.emit('autosave', this.getData());\n }, this.options.autoSaveInterval);\n }\n\n // Listen for structural block changes (add, remove, move, type-change)\n this.blockManager.on('change', () => {\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n });\n\n // Drag & drop files onto the editor\n this._blocksContainer.addEventListener('dragover', (e) => e.preventDefault());\n this._blocksContainer.addEventListener('drop', async (e) => {\n if (e.dataTransfer.files.length > 0) {\n e.preventDefault();\n const results = await this.mediaUploader.handleDrop(e.dataTransfer);\n if (results) {\n const target =\n (this._selectedBlockId && this.blockManager.getBlock(this._selectedBlockId)) ||\n this.blockManager.blocks[0] ||\n this.blockManager.addBlock('paragraph');\n if (!target) return;\n const chunks = [];\n for (const res of results) {\n if (res.error) continue;\n const type = this.mediaUploader.getMediaType(res.file);\n const src = res.remoteUrl || res.localUrl;\n if (!src) continue;\n if (type === 'image') chunks.push(`<img src=\"${src}\" alt=\"\">`);\n else if (type === 'video') chunks.push(`<video controls src=\"${src}\"></video>`);\n else if (type === 'audio') chunks.push(`<audio controls src=\"${src}\"></audio>`);\n else if (type === 'file') chunks.push(`<a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${res.file.name || 'Download file'}</a>`);\n }\n const toAppend = chunks.join('\\n');\n if (toAppend) target.content = `${target.content || ''}${target.content ? '\\n' : ''}${toAppend}`;\n this.render();\n this.focusBlock(target.id);\n }\n }\n });\n }\n\n /* ===== Rendering ===== */\n\n render() {\n this._ensureAtLeastOneBlock();\n this._blocksContainer.innerHTML = '';\n\n this.blockManager.blocks.forEach((block) => {\n const wrapper = el('section', {\n className: `fe-block-wrapper ${this._selectedBlockId === block.id ? 'fe-selected' : ''}`,\n dataset: { blockId: block.id },\n });\n\n // Toolbar (per-block, shown on selection)\n const tbContainer = el('div', { className: 'fe-block-toolbar-container' });\n if (this._selectedBlockId === block.id) {\n const tb = this.toolbar.create();\n this.toolbar.show(block.id);\n tb.scrollLeft = 0;\n tbContainer.appendChild(tb);\n requestAnimationFrame(() => this._positionBlockToolbar(tb, wrapper));\n }\n wrapper.appendChild(tbContainer);\n\n // Block content\n const rendered = this.blockRenderer.render(block);\n wrapper.appendChild(rendered);\n\n // Click to select\n wrapper.addEventListener('click', (e) => {\n const clickedContent = e.target.closest('.fe-block-content');\n const clickedEditable = e.target.closest('[contenteditable]');\n const clickedCell = e.target.closest('td,th');\n let clickedEditableIndex = -1;\n if (clickedEditable && wrapper.contains(clickedEditable)) {\n const editables = Array.from(wrapper.querySelectorAll('[contenteditable]'));\n clickedEditableIndex = editables.indexOf(clickedEditable);\n }\n let clickedCellPos = null;\n if (clickedCell) {\n const row = clickedCell.closest('tr');\n const table = clickedCell.closest('table');\n if (row && table) {\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n const cols = Array.from(row.querySelectorAll('th,td'));\n const colIndex = cols.indexOf(clickedCell);\n if (rowIndex >= 0 && colIndex >= 0) clickedCellPos = { rowIndex, colIndex };\n }\n }\n if (!e.target.closest('.fe-block-toolbar') && !e.target.closest('.fe-link-popover')) {\n if (this._selectedBlockId === block.id && (clickedContent || clickedEditable || clickedCell)) {\n return;\n }\n const blockId = block.id;\n this.selectBlock(blockId);\n // selectBlock calls render() which destroys DOM; focus the NEW contenteditable\n setTimeout(() => {\n const contentEl = this._getBlockContentEl(blockId);\n if (contentEl) {\n contentEl.focus();\n if (clickedCellPos) {\n const rows = Array.from(contentEl.querySelectorAll('tr'));\n const row = rows[clickedCellPos.rowIndex];\n const cols = row ? Array.from(row.querySelectorAll('th,td')) : [];\n const nextCell = cols[clickedCellPos.colIndex] || cols[cols.length - 1] || null;\n if (nextCell) {\n const range = document.createRange();\n range.selectNodeContents(nextCell);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n }\n if (clickedEditableIndex >= 0) {\n const newWrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n const editables = newWrapper ? Array.from(newWrapper.querySelectorAll('[contenteditable]')) : [];\n const targetEditable = editables[clickedEditableIndex] || editables[0] || null;\n if (targetEditable) {\n targetEditable.focus();\n placeCaretAtEnd(targetEditable);\n return;\n }\n }\n if (!clickedContent) placeCaretAtEnd(contentEl);\n }\n }, 0);\n }\n });\n\n // Drag handle setup\n const dragHandle = wrapper.querySelector('.fe-tb-drag');\n if (dragHandle) {\n const dd = new DragDrop(this._blocksContainer);\n dd.initDrag(dragHandle, wrapper, block.id);\n dd.on('drop', ({ fromId, toId, position }) => {\n const fromIdx = this.blockManager.getIndex(fromId);\n let toIdx = this.blockManager.getIndex(toId);\n if (position === 'after') toIdx++;\n if (fromIdx < toIdx) toIdx--;\n const [moved] = this.blockManager.blocks.splice(fromIdx, 1);\n this.blockManager.blocks.splice(toIdx, 0, moved);\n this.blockManager.saveSnapshot();\n this.render();\n });\n }\n\n this._blocksContainer.appendChild(wrapper);\n });\n\n // Single global appender (outside blocks) to match WP-like flow.\n const appender = el('button', {\n type: 'button',\n className: 'fe-block-appender',\n 'aria-label': 'Add block',\n });\n const plusIcon = el('span', { className: 'fe-plus-icon', innerHTML: icons.plus });\n const label = el('span', {}, ['Add block']);\n appender.appendChild(plusIcon);\n appender.appendChild(label);\n appender.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const targetId = this._selectedBlockId || this.blockManager.blocks[this.blockManager.blocks.length - 1]?.id;\n if (targetId) this.selectBlock(targetId);\n this.inserterPanel.open(appender, { forceNewBlock: true });\n });\n this._blocksContainer.appendChild(appender);\n\n this.statusBar.update();\n }\n\n /* ===== Block Operations ===== */\n\n selectBlock(id) {\n if (this._selectedBlockId === id) {\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n return;\n }\n this._selectedBlockId = id;\n this.render();\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n this.emit('block:select', id);\n }\n\n focusBlock(id) {\n this.selectBlock(id);\n setTimeout(() => {\n const contentEl = this._getBlockContentEl(id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtEnd(contentEl);\n }\n }, 0);\n }\n\n insertBlockAtSelection(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const selectedId = this._selectedBlockId;\n const block = this.blockManager.addBlock(type, data, selectedId || null);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n insertBlockAtEnd(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const block = this.blockManager.addBlock(type, data);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n /* ===== Block Input Handling ===== */\n\n _onBlockInput(block, node) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (node.textContent || '')\n : node.innerHTML;\n this.statusBar.update();\n\n // Slash command detection\n const text = node.textContent;\n if (text === '/') {\n const rect = getCaretRect() || node.getBoundingClientRect();\n this.slashMenu.open(block, rect);\n } else if (text.startsWith('/') && text.length > 1) {\n if (this.slashMenu.isOpen()) {\n this.slashMenu.filter(text.slice(1).toLowerCase());\n }\n } else {\n if (this.slashMenu.isOpen()) this.slashMenu.close();\n }\n\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n this.emit('input', block);\n }\n\n _onBlockKeydown(e, block, node) {\n // Slash menu takes priority\n if (this.slashMenu.isOpen() && this.slashMenu.handleKeydown(e)) return;\n // Keep Enter behavior inside the same block.\n // New blocks are created explicitly via inserter/add controls.\n\n // Table navigation + row creation with Tab\n if (e.key === 'Tab') {\n const cell = this._getSelectionTableCell();\n if (cell) {\n e.preventDefault();\n this._handleTableTab(cell, e.shiftKey);\n this._syncCurrentBlockContent();\n return;\n }\n }\n\n // Arrow Up at start: focus previous block\n if (e.key === 'ArrowUp') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.top <= nodeRect.top + 2) {\n const prev = this.blockManager.getPrevBlock(block.id);\n if (prev) {\n e.preventDefault();\n this.focusBlock(prev.id);\n }\n }\n }\n }\n\n // Arrow Down at end: focus next block\n if (e.key === 'ArrowDown') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.bottom >= nodeRect.bottom - 2) {\n const next = this.blockManager.getNextBlock(block.id);\n if (next) {\n e.preventDefault();\n const contentEl = this._getBlockContentEl(next.id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtStart(contentEl);\n this.selectBlock(next.id);\n }\n }\n }\n }\n }\n\n // Tab in code block\n if (e.key === 'Tab' && (block.type === 'code' || block.type === 'html')) {\n e.preventDefault();\n document.execCommand('insertText', false, ' ');\n }\n }\n\n /* ===== Helpers ===== */\n\n _getBlockContentEl(blockId) {\n const wrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n return wrapper?.querySelector('.fe-block-content') || wrapper?.querySelector('[contenteditable]');\n }\n\n _getSelectedBlockEl() {\n if (!this._selectedBlockId) return null;\n return this._blocksContainer.querySelector(`[data-block-id=\"${this._selectedBlockId}\"]`);\n }\n\n _syncCurrentBlockContent() {\n if (!this._selectedBlockId) return;\n const block = this.blockManager.getBlock(this._selectedBlockId);\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (block && contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n }\n\n _syncAllBlockContent() {\n this.blockManager.blocks.forEach((block) => {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n });\n }\n\n _generateSlug() {\n const slug = (this._titleEl?.value || '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n const slugEl = document.getElementById('fe-url-slug');\n if (slugEl) slugEl.value = slug;\n }\n\n _updateCanvasMargin() {\n if (!this.options.showSettingsPanel) return;\n const canvas = this.el.querySelector('.fe-editor-canvas');\n if (canvas) {\n canvas.classList.toggle('fe-panel-open', this.settingsPanel.isOpen());\n }\n }\n\n _createHtmlEditorModal() {\n const overlay = el('div', { className: 'fe-html-modal-overlay' });\n const modal = el('div', { className: 'fe-html-modal' });\n const header = el('div', { className: 'fe-html-modal-header' });\n const title = el('h3', { className: 'fe-html-modal-title' }, ['Edit as HTML']);\n const closeBtn = el('button', {\n type: 'button',\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this._closeBlockHtmlEditor(),\n });\n header.appendChild(title);\n header.appendChild(closeBtn);\n\n const textarea = el('textarea', {\n className: 'fe-html-modal-textarea',\n spellcheck: 'false',\n placeholder: 'Edit block HTML...',\n });\n\n const actions = el('div', { className: 'fe-html-modal-actions' });\n const cancelBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Cancel',\n onClick: () => this._closeBlockHtmlEditor(),\n });\n const applyBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Apply HTML',\n onClick: () => this._applyBlockHtmlEditor(),\n });\n actions.appendChild(cancelBtn);\n actions.appendChild(applyBtn);\n\n modal.appendChild(header);\n modal.appendChild(textarea);\n modal.appendChild(actions);\n overlay.appendChild(modal);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeBlockHtmlEditor();\n });\n textarea.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this._closeBlockHtmlEditor();\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') this._applyBlockHtmlEditor();\n });\n\n this.rootEl.appendChild(overlay);\n this._htmlEditorModal = overlay;\n this._htmlEditorTextarea = textarea;\n this._htmlEditorTitle = title;\n }\n\n _parseBlockFromHTML(html, fallbackType = 'paragraph') {\n const raw = (html || '').trim();\n if (!raw) return { type: fallbackType, content: '', attrs: {} };\n if (typeof document === 'undefined') return { type: 'html', content: raw, attrs: {} };\n\n const wrap = document.createElement('div');\n wrap.innerHTML = raw;\n const first = wrap.firstElementChild;\n const onlyOneElement =\n wrap.childElementCount === 1 &&\n Array.from(wrap.childNodes).every((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent.trim() === '');\n\n if (!first || !onlyOneElement) {\n return { type: 'html', content: raw, attrs: {} };\n }\n\n const tag = first.tagName.toLowerCase();\n if (tag === 'p') return { type: 'paragraph', content: first.innerHTML, attrs: {} };\n if (tag === 'h2') return { type: 'heading', content: first.innerHTML, attrs: {} };\n if (tag === 'h3') return { type: 'heading-3', content: first.innerHTML, attrs: {} };\n if (tag === 'h4') return { type: 'heading-4', content: first.innerHTML, attrs: {} };\n if (tag === 'blockquote') return { type: 'quote', content: first.innerHTML, attrs: {} };\n if (tag === 'ul') return { type: 'list', content: first.innerHTML, attrs: {} };\n if (tag === 'ol') return { type: 'ordered-list', content: first.innerHTML, attrs: {} };\n if (tag === 'hr') return { type: 'separator', content: '', attrs: {} };\n if (tag === 'img') {\n const styleWidth = _readPercentWidth(first.getAttribute('style') || '');\n return {\n type: 'image',\n content: first.getAttribute('src') || '',\n attrs: {\n alt: first.getAttribute('alt') || '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n if (tag === 'figure') {\n const img = first.querySelector('img');\n if (img) {\n const caption = first.querySelector('figcaption');\n const styleWidth = _readPercentWidth(img.getAttribute('style') || '');\n return {\n type: 'image',\n content: img.getAttribute('src') || '',\n attrs: {\n alt: img.getAttribute('alt') || '',\n caption: caption ? caption.innerHTML : '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n }\n if (tag === 'pre') {\n const code = first.querySelector('code');\n return {\n type: 'code',\n content: code ? (code.textContent || '') : (first.textContent || ''),\n attrs: {},\n };\n }\n\n return { type: 'html', content: raw, attrs: {} };\n }\n\n /* ===== Global Keyboard Shortcuts ===== */\n\n _handleGlobalKeydown(e) {\n const mod = e.ctrlKey || e.metaKey;\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.rootEl.contains(window.getSelection().anchorNode));\n\n if (mod && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n this.undo({ preferNative: inEditable });\n }\n if (mod && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\n e.preventDefault();\n this.redo({ preferNative: inEditable });\n }\n if (mod && e.key === 's') {\n e.preventDefault();\n this.save();\n }\n if (mod && e.key === 'b') {\n e.preventDefault();\n document.execCommand('bold', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'i') {\n e.preventDefault();\n document.execCommand('italic', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'u') {\n e.preventDefault();\n document.execCommand('underline', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'k') {\n e.preventDefault();\n this.toolbar._showLinkPopover();\n }\n if (mod && e.key === 'a') {\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (contentEl && this.rootEl.contains(document.activeElement)) {\n e.preventDefault();\n const range = document.createRange();\n range.selectNodeContents(contentEl);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n }\n\n /* ===== Public API ===== */\n\n /** Get all editor data as a JSON object. */\n getData() {\n this._syncAllBlockContent();\n const mergedHtml = this.blockManager.toHTML();\n return { content: mergedHtml };\n }\n\n /** Set editor content from a content string or { content } object. */\n setData(data) {\n const content = typeof data === 'string'\n ? data\n : (typeof data?.content === 'string' ? data.content : '');\n\n this.blockManager.fromJSON([\n {\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content,\n attrs: {},\n },\n ]);\n this.render();\n }\n\n /** Export blocks as HTML string. */\n toHTML() {\n this._syncAllBlockContent();\n return this.blockManager.toHTML();\n }\n\n toggleBlockHtmlMode(blockId = this._selectedBlockId) {\n if (!blockId) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n if (block.type === 'html') {\n const fallbackType = block.attrs?.__sourceType || 'paragraph';\n const parsed = this._parseBlockFromHTML(block.content || '', fallbackType);\n block.type = parsed.type === 'html' ? fallbackType : parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this.render();\n this.focusBlock(blockId);\n return;\n }\n\n const html = this.blockManager.blockToHTML(block);\n block.attrs = { ...(block.attrs || {}), __sourceType: block.type };\n block.type = 'html';\n block.content = html;\n this.render();\n this.focusBlock(blockId);\n }\n\n openBlockHtmlEditor(blockId = this._selectedBlockId) {\n if (!blockId || !this._htmlEditorModal || !this._htmlEditorTextarea) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n this._htmlEditorBlockId = blockId;\n this._htmlEditorTitle.textContent = `Edit as HTML: ${block.type}`;\n this._htmlEditorTextarea.value = this.blockManager.blockToHTML(block);\n this._htmlEditorModal.classList.add('fe-open');\n setTimeout(() => {\n this._htmlEditorTextarea.focus();\n this._htmlEditorTextarea.select();\n }, 0);\n }\n\n _closeBlockHtmlEditor() {\n if (!this._htmlEditorModal) return;\n this._htmlEditorModal.classList.remove('fe-open');\n this._htmlEditorBlockId = null;\n }\n\n _applyBlockHtmlEditor() {\n if (!this._htmlEditorBlockId || !this._htmlEditorTextarea) return;\n const block = this.blockManager.getBlock(this._htmlEditorBlockId);\n if (!block) return this._closeBlockHtmlEditor();\n\n const parsed = this._parseBlockFromHTML(this._htmlEditorTextarea.value, block.type);\n block.type = parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this._closeBlockHtmlEditor();\n this.render();\n this.focusBlock(block.id);\n }\n\n /** Save draft (emits save event). */\n save() {\n const data = this.getData();\n this.header.setStatus('Draft saved');\n this.statusBar.setSaved('Last saved: ' + new Date().toLocaleTimeString());\n this._showToast('Draft saved');\n if (this.options.onSave) this.options.onSave(data);\n this.emit('save', data);\n }\n\n /** Publish (emits publish event). */\n publish() {\n const data = this.getData();\n this.header.setStatus('Published', '#00a32a');\n this._showToast('Post published!');\n if (this.options.onPublish) this.options.onPublish(data);\n this.emit('publish', data);\n }\n\n /** Get / set the title. */\n getTitle() { return this._titleEl?.value || ''; }\n setTitle(title) { if (this._titleEl) this._titleEl.value = title; }\n\n undo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('undo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockUndo = this.blockManager.undo();\n if (didBlockUndo) this.render();\n return didBlockUndo;\n }\n\n redo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('redo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockRedo = this.blockManager.redo();\n if (didBlockRedo) this.render();\n return didBlockRedo;\n }\n\n /** Destroy editor instance. */\n destroy() {\n if (this._autoSaveTimer) clearInterval(this._autoSaveTimer);\n document.removeEventListener('keydown', this._boundGlobalKeydown);\n this.slashMenu.destroy();\n this.toolbar.hide();\n this.rootEl.innerHTML = '';\n this._listeners = {};\n }\n\n _showToast(msg) {\n this._toast.textContent = msg;\n this._toast.classList.add('fe-show');\n setTimeout(() => this._toast.classList.remove('fe-show'), 2500);\n }\n\n _positionBlockToolbar(toolbarEl, wrapperEl) {\n if (!toolbarEl || !wrapperEl) return;\n const viewportPadding = 8;\n\n toolbarEl.classList.remove('fe-toolbar-below');\n toolbarEl.style.top = '-44px';\n toolbarEl.style.left = '0px';\n\n const toolbarRect = toolbarEl.getBoundingClientRect();\n const wrapperRect = wrapperEl.getBoundingClientRect();\n\n let shiftX = 0;\n if (toolbarRect.right > window.innerWidth - viewportPadding) {\n shiftX -= toolbarRect.right - (window.innerWidth - viewportPadding);\n }\n if (toolbarRect.left + shiftX < viewportPadding) {\n shiftX += viewportPadding - (toolbarRect.left + shiftX);\n }\n toolbarEl.style.left = `${Math.round(shiftX)}px`;\n\n const topIfAbove = wrapperRect.top - toolbarRect.height - 6;\n const shouldPlaceBelow = topIfAbove < viewportPadding;\n if (shouldPlaceBelow) {\n toolbarEl.classList.add('fe-toolbar-below');\n toolbarEl.style.top = '6px';\n }\n wrapperEl.classList.toggle('fe-toolbar-inset', shouldPlaceBelow);\n }\n\n _getSelectionTableCell() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n let node = sel.anchorNode;\n if (!node) return null;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return null;\n const cell = node.closest('td,th');\n if (!cell) return null;\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (!contentEl || !contentEl.contains(cell)) return null;\n return cell;\n }\n\n _handleTableTab(currentCell, reverse = false) {\n const row = currentCell.closest('tr');\n const table = currentCell.closest('table');\n if (!row || !table) return;\n\n const rowCells = Array.from(row.querySelectorAll('th,td'));\n const cellIndex = rowCells.indexOf(currentCell);\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n\n if (reverse) {\n if (cellIndex > 0) {\n this._placeCaretInCell(rowCells[cellIndex - 1]);\n return;\n }\n if (rowIndex > 0) {\n const prevRowCells = Array.from(rows[rowIndex - 1].querySelectorAll('th,td'));\n this._placeCaretInCell(prevRowCells[prevRowCells.length - 1]);\n }\n return;\n }\n\n if (cellIndex < rowCells.length - 1) {\n this._placeCaretInCell(rowCells[cellIndex + 1]);\n return;\n }\n\n if (rowIndex < rows.length - 1) {\n const nextRowCells = Array.from(rows[rowIndex + 1].querySelectorAll('th,td'));\n this._placeCaretInCell(nextRowCells[0]);\n return;\n }\n\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n const tbody = table.querySelector('tbody');\n if (tbody) tbody.appendChild(newRow);\n else table.appendChild(newRow);\n this._placeCaretInCell(newRow.querySelector('td'));\n }\n\n _placeCaretInCell(cell) {\n if (!cell) return;\n if ((cell.innerHTML || '').trim() === '') cell.innerHTML = '<br>';\n const range = document.createRange();\n range.selectNodeContents(cell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n insertSingleBlockType(type, data = {}) {\n const block = this._getInsertionTargetBlock();\n if (!block) return false;\n\n const snippet = this._snippetForType(type, data);\n if (!snippet) return false;\n\n if (typeof document.execCommand === 'function') {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n contentEl.focus();\n const ok = document.execCommand('insertHTML', false, snippet);\n if (ok) {\n this._focusEditableTail(contentEl);\n this._syncCurrentBlockContent();\n return true;\n }\n }\n }\n\n block.content = `${block.content || ''}${block.content ? '\\n' : ''}${snippet}`;\n return true;\n }\n\n _snippetForType(type, data = {}) {\n if (type === 'separator') return '<hr><p><br></p>';\n if (type === 'spacer') return `<div style=\"height:${Number(data?.height) || 48}px\"></div><p><br></p>`;\n if (type === 'table') {\n return [\n '<table border=\"1\" style=\"width:100%;border-collapse:collapse;\">',\n '<tbody>',\n '<tr><td>Cell 1</td><td>Cell 2</td></tr>',\n '<tr><td>Cell 3</td><td>Cell 4</td></tr>',\n '</tbody>',\n '</table>',\n '<p><br></p>',\n ].join('');\n }\n if (type === 'columns') {\n return [\n '<div class=\"fe-inline-columns\">',\n '<div class=\"fe-inline-column\"><p>Column 1</p></div>',\n '<div class=\"fe-inline-column\"><p>Column 2</p></div>',\n '</div>',\n '<p><br></p>',\n ].join('');\n }\n\n if (type === 'button') {\n return '<p><a href=\"#\" style=\"display:inline-block;background:#2271b1;color:#fff;padding:10px 24px;border-radius:4px;text-decoration:none;\" contenteditable=\"false\">Button</a></p><p><br></p>';\n }\n if (type === 'video') {\n const src = String(data?.url || '').trim();\n return src\n ? `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`\n : '<video controls style=\"width:100%;max-width:100%;\"></video><p><br></p>';\n }\n if (type === 'audio') {\n const src = String(data?.url || '').trim();\n return src\n ? `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`\n : '<audio controls style=\"width:100%;\"></audio><p><br></p>';\n }\n if (type === 'file') {\n const url = String(data?.url || '').trim();\n const name = String(data?.name || 'Download file').trim();\n return url ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${name}</a></p><p><br></p>` : null;\n }\n if (type === 'embed') {\n const url = String(data?.url || '').trim();\n return url\n ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${url}</a></p><p><br></p>`\n : '<p>Paste embed URL here</p><p><br></p>';\n }\n return null;\n }\n\n _focusEditableTail(contentEl) {\n if (!contentEl) return;\n let tail = contentEl.lastElementChild;\n const needsTail = !tail || tail.tagName !== 'P';\n if (needsTail) {\n tail = document.createElement('p');\n tail.innerHTML = '<br>';\n contentEl.appendChild(tail);\n } else if ((tail.innerHTML || '').trim() === '') {\n tail.innerHTML = '<br>';\n }\n\n const range = document.createRange();\n range.selectNodeContents(tail);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n _ensureAtLeastOneBlock() {\n if (!Array.isArray(this.blockManager.blocks) || this.blockManager.blocks.length === 0) {\n return this.blockManager.addBlock('paragraph');\n }\n return this.blockManager.blocks[0];\n }\n\n _getInsertionTargetBlock() {\n const selected =\n this._selectedBlockId\n ? this.blockManager.getBlock(this._selectedBlockId)\n : null;\n if (selected) return selected;\n\n const last = this.blockManager.blocks[this.blockManager.blocks.length - 1];\n if (last) return last;\n\n return this.blockManager.addBlock('paragraph');\n }\n}\n\nfunction _readPercentWidth(style) {\n const match = /width\\s*:\\s*([0-9.]+)%/i.exec(style || '');\n if (!match) return null;\n const value = Number(match[1]);\n if (!Number.isFinite(value)) return null;\n return Math.max(10, Math.min(100, Math.round(value)));\n}\n","/**\n * React wrapper for NBDEditor.\n *\n * Guarded so the module can be safely imported in environments where React\n * is not available (e.g. vanilla-JS UMD usage). When React is missing,\n * `ReactNBDEditor` will be `null`.\n */\nimport * as React from 'react';\nimport { NBDEditor } from '../NBDEditor.js';\n\n// Guard: React may be undefined in vanilla-JS / UMD without React loaded.\nconst _hasReact = typeof React !== 'undefined' && React !== null && typeof React.forwardRef === 'function';\n\nfunction ReactNBDEditorComponent(props, ref) {\n const {\n className,\n style,\n content,\n onChange,\n onReady,\n ...editorOptions\n } = props || {};\n\n const hostRef = React.useRef(null);\n const editorRef = React.useRef(null);\n const lastContentRef = React.useRef(undefined);\n\n React.useEffect(() => {\n if (!hostRef.current) return undefined;\n\n const initialOptions = {\n ...editorOptions,\n onChange: (data) => {\n const nextContent = typeof data?.content === 'string' ? data.content : '';\n lastContentRef.current = nextContent;\n if (typeof onChange === 'function') onChange(data);\n },\n ...(typeof content === 'string' ? { content } : {}),\n };\n\n const editor = new NBDEditor(hostRef.current, initialOptions);\n editorRef.current = editor;\n lastContentRef.current = typeof content === 'string' ? content : undefined;\n if (typeof onReady === 'function') onReady(editor);\n\n return () => {\n if (editorRef.current) {\n editorRef.current.destroy();\n editorRef.current = null;\n }\n };\n // Intentionally one-time init; options should be stable at mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n React.useEffect(() => {\n if (!editorRef.current) return;\n if (typeof content !== 'string') return;\n if (content === lastContentRef.current) return;\n if (content === editorRef.current.toHTML()) {\n lastContentRef.current = content;\n return;\n }\n editorRef.current.setData({ content });\n lastContentRef.current = content;\n }, [content]);\n\n React.useImperativeHandle(ref, () => ({\n getInstance: () => editorRef.current,\n getData: () => editorRef.current?.getData(),\n setData: (data) => editorRef.current?.setData(data),\n toHTML: () => editorRef.current?.toHTML(),\n save: () => editorRef.current?.save(),\n publish: () => editorRef.current?.publish(),\n undo: (opts) => editorRef.current?.undo(opts),\n redo: (opts) => editorRef.current?.redo(opts),\n destroy: () => editorRef.current?.destroy(),\n }), []);\n\n return React.createElement('div', {\n ref: hostRef,\n className,\n style,\n });\n}\n\nexport const ReactNBDEditor = _hasReact ? React.forwardRef(ReactNBDEditorComponent) : null;\n"],"names":["EventEmitter","constructor","this","_listeners","on","event","fn","push","off","list","filter","f","emit","args","forEach","once","wrapper","el","tag","attrs","children","node","document","createElement","k","v","Object","entries","className","assign","style","dk","dv","dataset","startsWith","addEventListener","slice","toLowerCase","contentEditable","innerHTML","setAttribute","child","Array","isArray","appendChild","createTextNode","Node","generateId","Date","now","toString","Math","random","placeCaretAtEnd","element","focus","range","createRange","selectNodeContents","collapse","sel","window","getSelection","removeAllRanges","addRange","svg","inner","vb","icons","plus","undo","redo","listView","settings","bold","italic","underline","strikethrough","link","code","alignLeft","alignCenter","alignRight","image","heading","paragraph","quote","orderedList","separator","table","button","columns","spacer","embed","gallery","video","audio","file","dragHandle","filled","arrowUp","arrowDown","trash","close","inlineCode","upload","html","pullquote","BlockManager","super","blocks","_undoStack","_redoStack","_maxHistory","JSON","stringify","addBlock","type","data","afterId","block","id","content","idx","findIndex","b","splice","_pushUndo","removeBlock","length","removed","updateBlock","patch","getBlock","changeBlockType","newType","moveBlock","direction","newIdx","duplicateBlock","clone","find","getIndex","getPrevBlock","getNextBlock","toJSON","map","fromJSON","toHTML","blockToHTML","join","toHTMLBlocks","c","test","_escText","width","Number","isFinite","max","min","round","_escAttr","alt","caption","height","url","filename","next","shift","saveSnapshot","pop","parse","state","getWordCount","text","tmp","textContent","trim","split","w","getCharCount","replace","str","String","MediaUploader","options","uploadHandler","maxFileSize","allowedImageTypes","allowedVideoTypes","allowedAudioTypes","_fileInput","openFilePicker","accept","multiple","Promise","resolve","remove","input","display","body","files","click","processFile","size","err","name","toFixed","error","localUrl","_readAsDataURL","result","remoteUrl","message","processFiles","all","handlePaste","clipboardData","imageItems","items","item","getAsFile","Boolean","handleDrop","dataTransfer","getMediaType","reject","reader","FileReader","onload","onerror","readAsDataURL","DragDrop","container","_dragging","_placeholder","_offsetY","_bound","_enabled","enable","disable","initDrag","handleEl","wrapperEl","blockId","cursor","e","preventDefault","opacity","effectAllowed","setData","_removePlaceholder","dropEffect","rect","getBoundingClientRect","midY","top","position","clientY","_showPlaceholder","fromId","toId","referenceEl","cssText","parentNode","insertBefore","nextSibling","removeChild","BLOCK_TYPES","label","description","icon","category","hasContent","contentTag","placeholder","isMedia","CATEGORIES","getBlocksByCategory","catId","def","searchBlocks","query","q","includes","BlockRenderer","editor","render","_renderParagraph","_renderMediaBlock","_renderContentBlock","_renderSeparator","_renderSpacer","_renderColumns","_renderTable","isRawTextBlock","isEmpty","empty","_bindContentEvents","_renderImageBlock","_renderGalleryBlock","_renderVideoBlock","_renderAudioBlock","_renderFileBlock","_renderMediaPlaceholder","_normalizeImageWidth","fig","img","src","maxWidth","borderRadius","overlay","replaceBtn","onClick","_triggerImageUpload","removeBtn","resizeHandle","title","stopPropagation","selectBlock","startX","clientX","startWidth","parentWidth","onMove","ev","delta","nextPercent","onUp","removeEventListener","statusBar","update","sizeControls","pct","btn","images","grid","i","addMore","_triggerGalleryUpload","controls","infoDiv","filesize","downloadLink","href","download","iconEl","desc","btnRow","uploadBtn","_handleMediaUpload","urlInput","key","value","_setupDropZone","handle","startY","startH","newH","numCols","col","current","rows","cols","r","tr","cell","mediaUploader","results","res","bytes","classList","add","async","updateEmptyState","_selectedBlockId","activeElement","setTimeout","_onBlockInput","querySelector","_onBlockKeydown","getData","execCommand","then","numeric","Header","create","left","inserterBtn","inserterPanel","toggle","currentTarget","_iconBtn","activeEl","inEditable","isContentEditable","rootEl","contains","anchorNode","preferNative","center","right","showHeaderActions","draftBtn","save","publishBtn","publish","showSettingsPanel","childNodes","settingsPanel","_updateCanvasMargin","setStatus","color","iconHTML","Toolbar","_linkPopover","_fontSizeSelect","_onSelectionChange","_statefulButtons","_savedLinkRange","_tableToolsSep","_tableRowBtn","_tableColBtn","_createLinkPopover","show","blockManager","hide","getActiveBlockId","_addBtn","_addSep","textTypes","htmlEditableTypes","select","opt","o","selected","blockNow","ensureParagraphContext","contentEl","_getBlockContentEl","_syncCurrentBlockContent","focusBlock","fontSizeSelect","_applyFontSize","_syncFontSizeSelect","_bindFontSizeTracking","_addStatefulBtn","_exec","_wrapInlineCode","_showLinkPopover","_addTextBtn","_addTableRow","_addTableColumn","toggleBlockHtmlMode","_syncStatefulButtons","activeId","blockToClear","_hideLinkPopover","_unbindFontSizeTracking","extraClass","command","sep","cmd","rangeCount","getRangeAt","surroundContents","px","collapsed","marker","fontSize","insertNode","nextRange","setStart","firstChild","span","extractContents","_currentSelectionFontSizePx","snapped","sizes","best","bestDelta","abs","_closestFontSize","focusNode","elNode","nodeType","ELEMENT_NODE","parentElement","_getSelectedBlockEl","raw","getComputedStyle","parseFloat","applyBtn","_restoreSavedLinkRange","querySelectorAll","a","target","rel","cloneRange","bottom","anchor","closest","_getCurrentTableContext","TEXT_NODE","maybeCell","ctx","currentRow","rowCells","from","colCount","newRow","td","indexOf","row","cells","ref","newCell","tagName","targetRowCells","focusCell","hasSelectionInEditor","active","queryCommandState","tableDisplay","_isSelectionInTable","InserterPanel","_searchInput","_listEl","_anchorEl","_onDocMouseDown","_onDocKeyDown","_savedRange","_mediaModal","_mediaModalCard","_mediaModalTitle","_mediaModalBody","_mediaModalResolver","_forceNewBlock","header","closeBtn","_renderList","_createMediaModal","open","anchorEl","forceNewBlock","_captureSelectionRange","_positionNearAnchor","_bindGlobalCloseHandlers","_unbindGlobalCloseHandlers","isOpen","_createBlockItem","cat","blockDef","info","_insertFromPopover","desiredLeft","innerWidth","desiredTop","innerHeight","commonAncestorContainer","_restoreSelectionRange","selectedId","selectedBlock","insertSingleBlockType","insertBlockAtSelection","source","_chooseMediaSource","_promptForMediaUrl","trimmed","_showToast","prompt","onChooseMediaSource","_openMediaSourceModal","card","_closeMediaModal","actions","urlBtn","cancelBtn","resolver","SettingsPanel","_activeTab","_postTab","_blockTab","_tagInput","_tags","_categories","_featuredImage","tabs","_postTabBtn","_blockTabBtn","_switchTab","_buildPostTab","_buildBlockTab","updateBlockSettings","_blockSettingsContent","section","fontSelect","l","lhInput","lineHeight","colorSection","textColors","swatch","background","bgColors","border","tab","summary","_section","_field","cats","catList","addCat","checked","tags","tagWrapper","tagInput","val","t","fi","fiArea","fiInput","exc","disc","_toggle","s","frag","createDocumentFragment","defaultOn","SlashMenu","_visible","_highlightIndex","_items","_targetBlock","_boundDocClick","destroy","editorRect","_filter","handleKeydown","_navigate","visible","_selectItem","dir","scrollIntoView","StatusBar","_wordEl","_charEl","_blockEl","_savedEl","bm","titleText","_titleEl","titleWords","words","chars","setSaved","NBDEditor","selector","siteName","authorName","showStatusBar","autoSaveInterval","onChange","onSave","onPublish","Error","blockRenderer","toolbar","slashMenu","_blocksContainer","_autoSaveTimer","_htmlEditorModal","_htmlEditorTextarea","_htmlEditorTitle","_htmlEditorBlockId","_boundGlobalKeydown","_handleGlobalKeydown","_init","canvas","_toast","_createHtmlEditorModal","_ensureAtLeastOneBlock","setInterval","_syncAllBlockContent","toLocaleTimeString","chunks","toAppend","tbContainer","tb","scrollLeft","requestAnimationFrame","_positionBlockToolbar","rendered","clickedContent","clickedEditable","clickedCell","clickedEditableIndex","editables","clickedCellPos","rowIndex","colIndex","nextCell","newWrapper","targetEditable","dd","fromIdx","toIdx","moved","appender","plusIcon","targetId","_getInsertionTargetBlock","insertBlockAtEnd","getCaretRect","_getSelectionTableCell","_handleTableTab","shiftKey","nodeRect","prev","placeCaretAtStart","_generateSlug","slug","slugEl","getElementById","modal","_closeBlockHtmlEditor","textarea","spellcheck","_applyBlockHtmlEditor","ctrlKey","metaKey","_parseBlockFromHTML","fallbackType","wrap","first","firstElementChild","onlyOneElement","childElementCount","every","n","styleWidth","_readPercentWidth","getAttribute","mod","__sourceType","parsed","openBlockHtmlEditor","getTitle","setTitle","didBlockUndo","didBlockRedo","clearInterval","msg","toolbarEl","toolbarRect","wrapperRect","shiftX","shouldPlaceBelow","currentCell","reverse","cellIndex","_placeCaretInCell","prevRowCells","nextRowCells","tbody","snippet","_snippetForType","_focusEditableTail","tail","lastElementChild","last","match","exec","ReactNBDEditor","React","forwardRef","props","onReady","editorOptions","hostRef","useRef","editorRef","lastContentRef","undefined","useEffect","initialOptions","nextContent","useImperativeHandle","getInstance","opts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nbd-editor.umd.js","sources":["../src/utils/EventEmitter.js","../src/utils/dom.js","../src/utils/icons.js","../src/core/BlockManager.js","../src/core/MediaUploader.js","../src/core/DragDrop.js","../src/blocks/registry.js","../src/blocks/BlockRenderer.js","../src/ui/Header.js","../src/ui/Toolbar.js","../src/ui/InserterPanel.js","../src/ui/SettingsPanel.js","../src/ui/SlashMenu.js","../src/ui/StatusBar.js","../src/core/PluginRegistry.js","../src/core/Differ.js","../src/core/CollaborativeManager.js","../src/utils/sanitize.js","../src/utils/HtmlNormalizer.js","../src/formats/DeltaFormat.js","../src/NBDEditor.js","../src/react/ReactNBDEditor.js"],"sourcesContent":["/**\n * Lightweight event emitter for editor internals.\n */\nexport class EventEmitter {\n constructor() {\n this._listeners = {};\n }\n\n on(event, fn) {\n (this._listeners[event] ||= []).push(fn);\n return () => this.off(event, fn);\n }\n\n off(event, fn) {\n const list = this._listeners[event];\n if (!list) return;\n this._listeners[event] = list.filter((f) => f !== fn);\n }\n\n emit(event, ...args) {\n (this._listeners[event] || []).forEach((fn) => fn(...args));\n }\n\n once(event, fn) {\n const wrapper = (...args) => {\n this.off(event, wrapper);\n fn(...args);\n };\n this.on(event, wrapper);\n }\n}\n","/**\n * DOM helper utilities.\n */\n\nexport function el(tag, attrs = {}, children = []) {\n const node = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n if (k === 'className') node.className = v;\n else if (k === 'style' && typeof v === 'object') Object.assign(node.style, v);\n else if (k === 'dataset' && typeof v === 'object') {\n for (const [dk, dv] of Object.entries(v)) node.dataset[dk] = dv;\n } else if (k.startsWith('on') && typeof v === 'function') {\n node.addEventListener(k.slice(2).toLowerCase(), v);\n } else if (k === 'contentEditable') {\n node.contentEditable = v;\n } else if (k === 'innerHTML') {\n node.innerHTML = v;\n } else {\n node.setAttribute(k, v);\n }\n }\n for (const child of (Array.isArray(children) ? children : [children])) {\n if (typeof child === 'string') node.appendChild(document.createTextNode(child));\n else if (child instanceof Node) node.appendChild(child);\n }\n return node;\n}\n\nexport function qs(sel, root = document) {\n return root.querySelector(sel);\n}\n\nexport function qsa(sel, root = document) {\n return [...root.querySelectorAll(sel)];\n}\n\nexport function generateId() {\n return 'blk_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);\n}\n\nexport function stripHTML(html) {\n const tmp = document.createElement('div');\n tmp.innerHTML = html;\n return tmp.textContent || '';\n}\n\nexport function getCaretRect() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n return range.getBoundingClientRect();\n}\n\nexport function placeCaretAtEnd(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nexport function placeCaretAtStart(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n","/**\n * SVG icons used throughout the editor.\n */\n\nconst svg = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${inner}</svg>`;\n\nconst filled = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"currentColor\">${inner}</svg>`;\n\nexport const icons = {\n plus: svg('<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>'),\n undo: svg('<path d=\"M3 10h13a4 4 0 010 8H7\"/><path d=\"M3 10l4-4M3 10l4 4\"/>'),\n redo: svg('<path d=\"M21 10H8a4 4 0 000 8h9\"/><path d=\"M21 10l-4-4M21 10l-4 4\"/>'),\n listView: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"/>'),\n settings: svg('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\"/>'),\n moreVert: filled('<circle cx=\"12\" cy=\"5\" r=\"1.5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\"/><circle cx=\"12\" cy=\"19\" r=\"1.5\"/>'),\n bold: '<b>B</b>',\n italic: '<i>I</i>',\n underline: '<u>U</u>',\n strikethrough: '<s>S</s>',\n link: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n code: svg('<polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/>'),\n alignLeft: svg('<line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"/>'),\n alignCenter: svg('<line x1=\"18\" y1=\"10\" x2=\"6\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"18\" y1=\"18\" x2=\"6\" y2=\"18\"/>'),\n alignRight: svg('<line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"/>'),\n image: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>'),\n heading: '<b>H</b>',\n paragraph: '<span style=\"font-size:16px\">¶</span>',\n quote: '<span style=\"font-size:18px\">❝</span>',\n list: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" 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 orderedList: svg('<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\"/><text x=\"3\" y=\"8\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">1</text><text x=\"3\" y=\"14\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">2</text><text x=\"3\" y=\"20\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">3</text>'),\n separator: svg('<line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/>'),\n table: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><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 button: svg('<rect x=\"3\" y=\"7\" width=\"18\" height=\"10\" rx=\"3\"/>'),\n columns: svg('<rect x=\"3\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/>'),\n spacer: svg('<path d=\"M12 5v14M5 12h14\"/>', '0 0 24 24'),\n embed: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n gallery: svg('<rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"2\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/>'),\n video: svg('<polygon points=\"5 3 19 12 5 21 5 3\"/>'),\n audio: svg('<path d=\"M9 18V5l12-2v13\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><circle cx=\"18\" cy=\"16\" r=\"3\"/>'),\n file: svg('<path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/>'),\n dragHandle: filled('<circle cx=\"9\" cy=\"5\" r=\"1.2\"/><circle cx=\"15\" cy=\"5\" r=\"1.2\"/><circle cx=\"9\" cy=\"10\" r=\"1.2\"/><circle cx=\"15\" cy=\"10\" r=\"1.2\"/><circle cx=\"9\" cy=\"15\" r=\"1.2\"/><circle cx=\"15\" cy=\"15\" r=\"1.2\"/><circle cx=\"9\" cy=\"20\" r=\"1.2\"/><circle cx=\"15\" cy=\"20\" r=\"1.2\"/>'),\n arrowUp: svg('<polyline points=\"18 15 12 9 6 15\"/>'),\n arrowDown: svg('<polyline points=\"6 9 12 15 18 9\"/>'),\n trash: svg('<polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/>'),\n close: svg('<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>'),\n check: svg('<polyline points=\"20 6 9 17 4 12\"/>'),\n inlineCode: '<span style=\"font-family:monospace;font-size:13px\"></></span>',\n upload: svg('<path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\"/><polyline points=\"17 8 12 3 7 8\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"/>'),\n externalLink: svg('<path d=\"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/>'),\n html: '<span style=\"font-family:monospace;font-size:11px\"><HTML></span>',\n pullquote: svg('<path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/>'),\n};\n","import { generateId } from '../utils/dom.js';\nimport { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Manages the block data model: add, remove, move, update, and undo/redo.\n */\nexport class BlockManager extends EventEmitter {\n constructor() {\n super();\n this.blocks = [];\n this._undoStack = [];\n this._redoStack = [];\n this._maxHistory = 100;\n this._undoStack.push(JSON.stringify(this.blocks));\n }\n\n /* ---- CRUD ---- */\n\n addBlock(type, data = {}, afterId = null) {\n const block = {\n id: generateId(),\n type,\n content: '',\n attrs: {},\n ...data,\n };\n\n if (afterId) {\n const idx = this.blocks.findIndex((b) => b.id === afterId);\n this.blocks.splice(idx + 1, 0, block);\n } else {\n this.blocks.push(block);\n }\n\n this._pushUndo();\n this.emit('block:added', block);\n this.emit('change', this.blocks);\n return block;\n }\n\n removeBlock(id) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n if (idx === -1) return;\n if (this.blocks.length <= 1) return; // keep at least one block\n const [removed] = this.blocks.splice(idx, 1);\n this._pushUndo();\n this.emit('block:removed', removed, idx);\n this.emit('change', this.blocks);\n return removed;\n }\n\n updateBlock(id, patch) {\n const block = this.getBlock(id);\n if (!block) return;\n Object.assign(block, patch);\n this.emit('block:updated', block);\n this.emit('change', this.blocks);\n }\n\n changeBlockType(id, newType) {\n const block = this.getBlock(id);\n if (!block) return;\n block.type = newType;\n this._pushUndo();\n this.emit('block:typeChanged', block);\n this.emit('change', this.blocks);\n }\n\n moveBlock(id, direction) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n const newIdx = idx + direction;\n if (newIdx < 0 || newIdx >= this.blocks.length) return;\n [this.blocks[idx], this.blocks[newIdx]] = [this.blocks[newIdx], this.blocks[idx]];\n this._pushUndo();\n this.emit('block:moved', this.blocks[newIdx], direction);\n this.emit('change', this.blocks);\n }\n\n duplicateBlock(id) {\n const block = this.getBlock(id);\n if (!block) return;\n const clone = { ...block, id: generateId(), content: block.content, attrs: { ...block.attrs } };\n const idx = this.blocks.findIndex((b) => b.id === id);\n this.blocks.splice(idx + 1, 0, clone);\n this._pushUndo();\n this.emit('block:added', clone);\n this.emit('change', this.blocks);\n return clone;\n }\n\n /* ---- Queries ---- */\n\n getBlock(id) {\n return this.blocks.find((b) => b.id === id) || null;\n }\n\n getIndex(id) {\n return this.blocks.findIndex((b) => b.id === id);\n }\n\n getPrevBlock(id) {\n const idx = this.getIndex(id);\n return idx > 0 ? this.blocks[idx - 1] : null;\n }\n\n getNextBlock(id) {\n const idx = this.getIndex(id);\n return idx < this.blocks.length - 1 ? this.blocks[idx + 1] : null;\n }\n\n /* ---- Serialization ---- */\n\n toJSON() {\n return this.blocks.map((b) => ({ ...b }));\n }\n\n fromJSON(data) {\n this.blocks = data.map((b) => ({ ...b }));\n this._undoStack = [JSON.stringify(this.blocks)];\n this._redoStack = [];\n this.emit('change', this.blocks);\n }\n\n toHTML() {\n return this.blocks.map((b) => this.blockToHTML(b)).join('\\n');\n }\n\n toHTMLBlocks() {\n return this.blocks.map((b) => ({\n ...b,\n html: this.blockToHTML(b),\n }));\n }\n\n blockToHTML(block) {\n return blockToHTML(block);\n }\n\n /* ---- Undo / Redo ---- */\n\n _pushUndo() {\n const next = JSON.stringify(this.blocks);\n const last = this._undoStack[this._undoStack.length - 1];\n if (next === last) return;\n this._undoStack.push(next);\n if (this._undoStack.length > this._maxHistory) this._undoStack.shift();\n this._redoStack = [];\n }\n\n saveSnapshot() {\n this._pushUndo();\n }\n\n undo() {\n if (this._undoStack.length < 2) return false;\n this._redoStack.push(this._undoStack.pop());\n this.blocks = JSON.parse(this._undoStack[this._undoStack.length - 1]);\n this.emit('change', this.blocks);\n return true;\n }\n\n redo() {\n if (this._redoStack.length === 0) return false;\n const state = this._redoStack.pop();\n this._undoStack.push(state);\n this.blocks = JSON.parse(state);\n this.emit('change', this.blocks);\n return true;\n }\n\n /* ---- Stats ---- */\n\n getWordCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent + ' ';\n }\n }\n const words = text.trim().split(/\\s+/).filter((w) => w.length > 0);\n return words.length;\n }\n\n getCharCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent;\n }\n }\n return text.replace(/\\s/g, '').length;\n }\n}\n\n/* ---- Helpers ---- */\n\n/**\n * Escape a string for safe use inside an HTML attribute value.\n * Prevents XSS via attribute injection (e.g. `\" onload=\"alert(1)`).\n */\nfunction _escAttr(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\n/**\n * Escape a string for safe use as HTML text content.\n */\nfunction _escText(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nfunction blockToHTML(block) {\n const c = block.content || '';\n switch (block.type) {\n case 'paragraph':\n return _containsBlockMarkup(c) ? c : `<p>${c}</p>`;\n case 'heading':\n return `<h2>${c}</h2>`;\n case 'heading-3':\n return `<h3>${c}</h3>`;\n case 'heading-4':\n return `<h4>${c}</h4>`;\n case 'quote':\n return `<blockquote>${c}</blockquote>`;\n case 'code':\n return `<pre><code>${_escText(c)}</code></pre>`;\n case 'list':\n return /^\\s*<ul[\\s>]/i.test(c) ? c : `<ul>${c}</ul>`;\n case 'ordered-list':\n return /^\\s*<ol[\\s>]/i.test(c) ? c : `<ol>${c}</ol>`;\n case 'image': {\n if (!c) return '';\n const width = Number(block.attrs?.width);\n const style = Number.isFinite(width) ? ` style=\"width:${Math.max(10, Math.min(100, Math.round(width)))}%\"` : '';\n return `<figure><img src=\"${_escAttr(c)}\" alt=\"${_escAttr(block.attrs?.alt || '')}\"${style}/>${block.attrs?.caption ? `<figcaption>${block.attrs.caption}</figcaption>` : ''}</figure>`;\n }\n case 'separator':\n return '<hr/>';\n case 'spacer':\n return `<div style=\"height:${Number(block.attrs?.height) || 48}px\"></div>`;\n case 'table': {\n if (c) return c;\n const data = block.attrs?.data;\n const rows = block.attrs?.rows || 3;\n const cols = block.attrs?.cols || 3;\n if (!data || data.length === 0) return '<table></table>';\n let html = '<table>';\n for (let r = 0; r < rows; r++) {\n html += '<tr>';\n for (let ci = 0; ci < cols; ci++) {\n const tag = r === 0 ? 'th' : 'td';\n html += `<${tag}>${data[r]?.[ci] || ''}</${tag}>`;\n }\n html += '</tr>';\n }\n html += '</table>';\n return html;\n }\n case 'button':\n return `<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"${_escAttr(block.attrs?.url || '#')}\">${c || 'Button'}</a></div>`;\n case 'columns': {\n if (c) return `<div class=\"wp-block-columns\">${c}</div>`;\n const numCols = block.attrs?.columns || 2;\n let colsHTML = '';\n for (let i = 0; i < numCols; i++) {\n colsHTML += `<div class=\"wp-block-column\">${block.attrs?.[`col${i}`] || ''}</div>`;\n }\n return `<div class=\"wp-block-columns\">${colsHTML}</div>`;\n }\n case 'embed':\n return `<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">${c}</div></figure>`;\n case 'gallery':\n return `<figure class=\"wp-block-gallery\">${c}</figure>`;\n case 'video':\n return c ? `<figure class=\"wp-block-video\"><video controls src=\"${_escAttr(c)}\"></video></figure>` : '';\n case 'audio':\n return c ? `<figure class=\"wp-block-audio\"><audio controls src=\"${_escAttr(c)}\"></audio></figure>` : '';\n case 'file':\n return c ? `<div class=\"wp-block-file\"><a href=\"${_escAttr(c)}\">${_escText(block.attrs?.filename || 'Download')}</a></div>` : '';\n case 'html':\n return c;\n case 'pullquote':\n return `<figure class=\"wp-block-pullquote\"><blockquote>${c}</blockquote></figure>`;\n default:\n return `<p>${c}</p>`;\n }\n}\n\nfunction _containsBlockMarkup(html) {\n if (!html || typeof html !== 'string') return false;\n return /<(h[1-6]|p|div|section|article|blockquote|ul|ol|li|table|thead|tbody|tr|td|th|figure|figcaption|img|pre|hr)\\b/i.test(html);\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Handles media uploads: images, video, audio, files.\n * Supports custom upload handlers, drag-and-drop, clipboard paste, and local preview.\n */\nexport class MediaUploader extends EventEmitter {\n constructor(options = {}) {\n super();\n this.uploadHandler = options.uploadHandler || null; // async (file) => { url, id }\n this.maxFileSize = options.maxFileSize || 10 * 1024 * 1024; // 10MB\n this.allowedImageTypes = options.allowedImageTypes || ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];\n this.allowedVideoTypes = options.allowedVideoTypes || ['video/mp4', 'video/webm', 'video/ogg'];\n this.allowedAudioTypes = options.allowedAudioTypes || ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/webm'];\n this._fileInput = null;\n }\n\n /**\n * Create a hidden file input and trigger it.\n */\n openFilePicker(accept = 'image/*', multiple = false) {\n return new Promise((resolve) => {\n if (this._fileInput) this._fileInput.remove();\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = accept;\n input.multiple = multiple;\n input.style.display = 'none';\n document.body.appendChild(input);\n this._fileInput = input;\n\n input.addEventListener('change', () => {\n const files = [...input.files];\n input.remove();\n this._fileInput = null;\n resolve(files);\n });\n\n input.addEventListener('cancel', () => {\n input.remove();\n this._fileInput = null;\n resolve([]);\n });\n\n input.click();\n });\n }\n\n /**\n * Process a file: validate, generate local preview, then optionally upload.\n * Returns { localUrl, remoteUrl?, file, error? }\n */\n async processFile(file) {\n // Validate size\n if (file.size > this.maxFileSize) {\n const err = `File \"${file.name}\" exceeds the ${(this.maxFileSize / 1024 / 1024).toFixed(0)}MB limit.`;\n this.emit('error', err);\n return { error: err, file };\n }\n\n // Generate local preview\n const localUrl = await this._readAsDataURL(file);\n this.emit('preview', { file, localUrl });\n\n // If a custom upload handler is provided, use it\n if (this.uploadHandler) {\n try {\n this.emit('upload:start', { file });\n const result = await this.uploadHandler(file);\n this.emit('upload:complete', { file, ...result });\n return { localUrl, remoteUrl: result.url, file, id: result.id };\n } catch (err) {\n this.emit('upload:error', { file, error: err });\n return { localUrl, file, error: err.message || 'Upload failed' };\n }\n }\n\n // No remote handler — just use local data URL\n return { localUrl, file };\n }\n\n /**\n * Process multiple files.\n */\n async processFiles(files) {\n return Promise.all(files.map((f) => this.processFile(f)));\n }\n\n /**\n * Handle a paste event for images.\n */\n async handlePaste(clipboardData) {\n const items = [...(clipboardData.items || [])];\n const imageItems = items.filter((item) => item.type.startsWith('image/'));\n if (imageItems.length === 0) return null;\n\n const files = imageItems.map((item) => item.getAsFile()).filter(Boolean);\n if (files.length === 0) return null;\n\n return this.processFiles(files);\n }\n\n /**\n * Handle drag-and-drop of files.\n */\n async handleDrop(dataTransfer) {\n const files = [...(dataTransfer.files || [])];\n if (files.length === 0) return null;\n return this.processFiles(files);\n }\n\n /**\n * Determine media type from file.\n */\n getMediaType(file) {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type.startsWith('video/')) return 'video';\n if (file.type.startsWith('audio/')) return 'audio';\n return 'file';\n }\n\n /**\n * Read file as data URL.\n */\n _readAsDataURL(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n }\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Drag-and-drop reordering for blocks.\n */\nexport class DragDrop extends EventEmitter {\n constructor(container) {\n super();\n this.container = container;\n this._dragging = null;\n this._placeholder = null;\n this._offsetY = 0;\n this._bound = {};\n this._enabled = true;\n }\n\n enable() {\n this._enabled = true;\n }\n\n disable() {\n this._enabled = false;\n }\n\n /**\n * Initialise drag on a handle element within a block wrapper.\n */\n initDrag(handleEl, wrapperEl, blockId) {\n handleEl.setAttribute('draggable', 'true');\n handleEl.style.cursor = 'grab';\n\n handleEl.addEventListener('dragstart', (e) => {\n if (!this._enabled) return e.preventDefault();\n this._dragging = { el: wrapperEl, id: blockId };\n wrapperEl.style.opacity = '0.4';\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', blockId);\n this.emit('drag:start', blockId);\n });\n\n handleEl.addEventListener('dragend', () => {\n if (this._dragging) {\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n }\n this._removePlaceholder();\n this.emit('drag:end');\n });\n\n wrapperEl.addEventListener('dragover', (e) => {\n if (!this._dragging || this._dragging.id === blockId) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._showPlaceholder(wrapperEl, position);\n });\n\n wrapperEl.addEventListener('drop', (e) => {\n e.preventDefault();\n if (!this._dragging) return;\n const fromId = this._dragging.id;\n const toId = blockId;\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._removePlaceholder();\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n\n this.emit('drop', { fromId, toId, position });\n });\n }\n\n _showPlaceholder(referenceEl, position) {\n if (!this._placeholder) {\n this._placeholder = document.createElement('div');\n this._placeholder.className = 'fe-drag-placeholder';\n this._placeholder.style.cssText =\n 'height:4px;background:#2271b1;border-radius:2px;margin:4px 0;transition:all 0.15s;';\n }\n if (position === 'before') {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl);\n } else {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl.nextSibling);\n }\n }\n\n _removePlaceholder() {\n if (this._placeholder && this._placeholder.parentNode) {\n this._placeholder.parentNode.removeChild(this._placeholder);\n }\n }\n}\n","import { icons } from '../utils/icons.js';\n\n/**\n * Block type registry. Each entry describes a block type and how to render it.\n */\nexport const BLOCK_TYPES = {\n paragraph: {\n label: 'Paragraph',\n description: 'Start with the building block of all narrative.',\n icon: icons.paragraph,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Type / to choose a block',\n className: '',\n },\n heading: {\n label: 'Heading 2',\n description: 'Introduce new sections and organize content.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h2',\n placeholder: 'Heading 2',\n className: 'fe-heading-2',\n },\n 'heading-3': {\n label: 'Heading 3',\n description: 'A smaller heading for subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h3',\n placeholder: 'Heading 3',\n className: 'fe-heading-3',\n },\n 'heading-4': {\n label: 'Heading 4',\n description: 'A small heading for nested subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h4',\n placeholder: 'Heading 4',\n className: 'fe-heading-4',\n },\n list: {\n label: 'List',\n description: 'Create a bulleted list.',\n icon: icons.list,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-list-block',\n },\n 'ordered-list': {\n label: 'Ordered List',\n description: 'Create a numbered list.',\n icon: icons.orderedList,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-ordered-list-block',\n },\n quote: {\n label: 'Quote',\n description: 'Give quoted text visual emphasis.',\n icon: icons.quote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write quote...',\n className: 'fe-quote',\n },\n pullquote: {\n label: 'Pullquote',\n description: 'Highlight a key quote from your content.',\n icon: icons.pullquote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write pullquote...',\n className: 'fe-pullquote',\n },\n code: {\n label: 'Code',\n description: 'Display code snippets that respect your spacing.',\n icon: icons.code,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write code...',\n className: 'fe-code-block',\n },\n html: {\n label: 'Custom HTML',\n description: 'Add custom HTML code.',\n icon: icons.html,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write HTML...',\n className: 'fe-html-block',\n },\n image: {\n label: 'Image',\n description: 'Insert an image to make a visual statement.',\n icon: icons.image,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n gallery: {\n label: 'Gallery',\n description: 'Display multiple images in a gallery.',\n icon: icons.gallery,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n video: {\n label: 'Video',\n description: 'Embed a video from your media library or URL.',\n icon: icons.video,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n audio: {\n label: 'Audio',\n description: 'Embed an audio file.',\n icon: icons.audio,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n file: {\n label: 'File',\n description: 'Add a link to a downloadable file.',\n icon: icons.file,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n separator: {\n label: 'Separator',\n description: 'Create a break between ideas or sections.',\n icon: icons.separator,\n category: 'design',\n hasContent: false,\n },\n spacer: {\n label: 'Spacer',\n description: 'Add white space between blocks.',\n icon: icons.spacer,\n category: 'design',\n hasContent: false,\n },\n columns: {\n label: 'Columns',\n description: 'Display content in multiple columns.',\n icon: icons.columns,\n category: 'design',\n hasContent: false,\n },\n table: {\n label: 'Table',\n description: 'Insert a table for sharing data.',\n icon: icons.table,\n category: 'design',\n hasContent: false,\n },\n button: {\n label: 'Button',\n description: 'Prompt visitors to take action with a button.',\n icon: icons.button,\n category: 'design',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Add text...',\n className: 'fe-button-block',\n },\n embed: {\n label: 'Embed',\n description: 'Embed content from YouTube, Twitter, etc.',\n icon: icons.embed,\n category: 'media',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Enter URL to embed...',\n className: 'fe-embed-block',\n },\n};\n\nexport const CATEGORIES = [\n { id: 'text', label: 'Text' },\n { id: 'media', label: 'Media' },\n { id: 'design', label: 'Design' },\n];\n\n/**\n * Get blocks for a category.\n */\nexport function getBlocksByCategory(catId) {\n return Object.entries(BLOCK_TYPES)\n .filter(([, def]) => def.category === catId)\n .map(([type, def]) => ({ type, ...def }));\n}\n\n/**\n * Search blocks by query.\n */\nexport function searchBlocks(query) {\n const q = query.toLowerCase();\n return Object.entries(BLOCK_TYPES)\n .filter(([type, def]) => type.includes(q) || def.label.toLowerCase().includes(q) || def.description.toLowerCase().includes(q))\n .map(([type, def]) => ({ type, ...def }));\n}\n","import { el, placeCaretAtEnd } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { BLOCK_TYPES } from './registry.js';\n\n/**\n * Creates the DOM for a single block based on its type and data.\n */\nexport class BlockRenderer {\n constructor(editor) {\n this.editor = editor;\n }\n\n render(block) {\n const def = BLOCK_TYPES[block.type];\n if (!def) return this._renderParagraph(block);\n\n if (def.isMedia) return this._renderMediaBlock(block, def);\n if (def.hasContent) return this._renderContentBlock(block, def);\n\n // Non-content blocks\n switch (block.type) {\n case 'separator': return this._renderSeparator(block);\n case 'spacer': return this._renderSpacer(block);\n case 'columns': return this._renderColumns(block);\n case 'table': return this._renderTable(block);\n default: return this._renderParagraph(block);\n }\n }\n\n /* ---- Content Blocks (editable) ---- */\n\n _renderContentBlock(block, def) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n const isEmpty = !block.content || block.content.trim() === '';\n\n // List blocks need proper <ul>/<ol> structure to work correctly\n let initialHTML;\n if (isRawTextBlock) {\n initialHTML = '';\n } else if (isEmpty && block.type === 'list') {\n initialHTML = '<ul><li><br></li></ul>';\n } else if (isEmpty && block.type === 'ordered-list') {\n initialHTML = '<ol><li><br></li></ol>';\n } else {\n initialHTML = block.content || '<br>';\n }\n\n const node = el(def.contentTag || 'div', {\n className: `fe-block-content ${def.className || ''}`.trim(),\n contentEditable: 'true',\n dataset: {\n placeholder: def.placeholder || '',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: initialHTML,\n });\n if (isRawTextBlock && block.content) {\n node.textContent = block.content;\n }\n\n this._bindContentEvents(node, block);\n return node;\n }\n\n _renderParagraph(block) {\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el('div', {\n className: 'fe-block-content',\n contentEditable: 'true',\n dataset: { \n placeholder: 'Type / to choose a block',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: block.content || '<br>',\n });\n this._bindContentEvents(node, block);\n return node;\n }\n\n /* ---- Media Blocks ---- */\n\n _renderMediaBlock(block, def) {\n const container = el('div', { className: `fe-block-media fe-block-${block.type}` });\n\n switch (block.type) {\n case 'image':\n return this._renderImageBlock(block, container);\n case 'gallery':\n return this._renderGalleryBlock(block, container);\n case 'video':\n return this._renderVideoBlock(block, container);\n case 'audio':\n return this._renderAudioBlock(block, container);\n case 'file':\n return this._renderFileBlock(block, container);\n default:\n return this._renderMediaPlaceholder(block, container, def);\n }\n }\n\n _renderImageBlock(block, container) {\n if (block.content) {\n const width = _normalizeImageWidth(block.attrs?.width);\n const fig = el('figure', { className: 'fe-image-figure' });\n const img = el('img', { src: block.content, alt: block.attrs?.alt || '' });\n img.style.width = `${width}%`;\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n img.style.display = 'block';\n fig.appendChild(img);\n\n // Caption\n const caption = el('figcaption', {\n className: 'fe-image-caption',\n contentEditable: 'true',\n dataset: { placeholder: 'Add caption...' },\n innerHTML: block.attrs?.caption || '',\n });\n caption.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs.caption = caption.innerHTML;\n });\n fig.appendChild(caption);\n\n // Toolbar overlay\n const overlay = el('div', { className: 'fe-image-overlay' });\n const replaceBtn = el('button', {\n className: 'fe-img-overlay-btn',\n innerHTML: 'Replace',\n onClick: () => this._triggerImageUpload(block),\n });\n const removeBtn = el('button', {\n className: 'fe-img-overlay-btn fe-img-overlay-btn-danger',\n innerHTML: 'Remove',\n onClick: () => {\n block.content = '';\n block.attrs = {};\n this.editor.render();\n },\n });\n overlay.appendChild(replaceBtn);\n overlay.appendChild(removeBtn);\n fig.appendChild(overlay);\n\n const resizeHandle = el('button', {\n type: 'button',\n className: 'fe-image-resize-handle',\n title: 'Drag to resize image',\n });\n resizeHandle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.editor.selectBlock(block.id);\n\n const startX = e.clientX;\n const startWidth = img.getBoundingClientRect().width;\n const parentWidth = container.getBoundingClientRect().width || startWidth || 1;\n\n const onMove = (ev) => {\n const delta = ev.clientX - startX;\n const nextWidthPx = Math.max(80, Math.min(parentWidth, startWidth + delta));\n const nextPercent = _normalizeImageWidth((nextWidthPx / parentWidth) * 100);\n block.attrs = block.attrs || {};\n block.attrs.width = nextPercent;\n img.style.width = `${nextPercent}%`;\n };\n\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this.editor.statusBar.update();\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n fig.appendChild(resizeHandle);\n\n container.appendChild(fig);\n\n const sizeControls = el('div', { className: 'fe-image-size-controls' });\n [25, 50, 75, 100].forEach((pct) => {\n const btn = el('button', {\n type: 'button',\n className: `fe-img-size-btn ${width === pct ? 'is-active' : ''}`.trim(),\n innerHTML: `${pct}%`,\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.width = pct;\n this.editor.render();\n },\n });\n sizeControls.appendChild(btn);\n });\n container.appendChild(sizeControls);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.image);\n }\n\n return container;\n }\n\n _renderGalleryBlock(block, container) {\n const images = block.attrs?.images || [];\n if (images.length > 0) {\n const grid = el('div', { className: 'fe-gallery-grid' });\n images.forEach((src, i) => {\n const item = el('div', { className: 'fe-gallery-item' });\n item.appendChild(el('img', { src, alt: '' }));\n const removeBtn = el('button', {\n className: 'fe-gallery-remove',\n innerHTML: '×',\n onClick: () => {\n images.splice(i, 1);\n this.editor.render();\n },\n });\n item.appendChild(removeBtn);\n grid.appendChild(item);\n });\n container.appendChild(grid);\n\n const addMore = el('button', {\n className: 'fe-gallery-add',\n innerHTML: '+ Add Images',\n onClick: () => this._triggerGalleryUpload(block),\n });\n container.appendChild(addMore);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.gallery);\n }\n return container;\n }\n\n _renderVideoBlock(block, container) {\n if (block.content) {\n const video = el('video', { src: block.content });\n video.controls = true;\n video.style.maxWidth = '100%';\n video.style.borderRadius = '4px';\n container.appendChild(video);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.video);\n }\n return container;\n }\n\n _renderAudioBlock(block, container) {\n if (block.content) {\n const audio = el('audio', { src: block.content });\n audio.controls = true;\n audio.style.width = '100%';\n container.appendChild(audio);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.audio);\n }\n return container;\n }\n\n _renderFileBlock(block, container) {\n if (block.content) {\n const wrapper = el('div', { className: 'fe-file-wrapper' });\n\n const infoDiv = el('div', { className: 'fe-file-info' });\n infoDiv.appendChild(el('span', { className: 'fe-file-icon', innerHTML: icons.file }));\n infoDiv.appendChild(el('span', { className: 'fe-file-name' }, [block.attrs?.filename || 'File']));\n infoDiv.appendChild(el('span', { className: 'fe-file-size' }, [block.attrs?.filesize || '']));\n wrapper.appendChild(infoDiv);\n\n const downloadLink = el('a', { className: 'fe-file-download', href: block.content, download: '' }, ['Download']);\n wrapper.appendChild(downloadLink);\n\n container.appendChild(wrapper);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.file);\n }\n return container;\n }\n\n _renderMediaPlaceholder(block, container, def) {\n const placeholder = el('div', { className: 'fe-media-placeholder' });\n\n const iconEl = el('div', { className: 'fe-media-placeholder-icon', innerHTML: def.icon });\n const label = el('p', { className: 'fe-media-placeholder-label' }, [def.label]);\n const desc = el('p', { className: 'fe-media-placeholder-desc' }, ['Upload a file or pick one from your media library.']);\n\n const btnRow = el('div', { className: 'fe-media-placeholder-actions' });\n\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: `${icons.upload} Upload`,\n onClick: () => this._handleMediaUpload(block),\n });\n btnRow.appendChild(uploadBtn);\n\n // URL input for embeds, video, audio\n if (['embed', 'video', 'audio'].includes(block.type)) {\n const urlInput = el('input', {\n type: 'text',\n className: 'fe-media-url-input',\n placeholder: 'Or paste a URL...',\n });\n urlInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n block.content = urlInput.value;\n this.editor.render();\n }\n });\n btnRow.appendChild(urlInput);\n }\n\n placeholder.appendChild(iconEl);\n placeholder.appendChild(label);\n placeholder.appendChild(desc);\n placeholder.appendChild(btnRow);\n container.appendChild(placeholder);\n\n // Drop zone\n this._setupDropZone(placeholder, block);\n\n return container;\n }\n\n /* ---- Non-content Blocks ---- */\n\n _renderSeparator(block) {\n const node = el('div', { className: 'fe-block-separator' });\n node.appendChild(el('hr'));\n return node;\n }\n\n _renderSpacer(block) {\n const height = block.attrs?.height || 48;\n const node = el('div', {\n className: 'fe-block-spacer',\n style: { height: height + 'px' },\n });\n\n // Resize handle\n const handle = el('div', { className: 'fe-spacer-handle' });\n let startY, startH;\n handle.addEventListener('mousedown', (e) => {\n startY = e.clientY;\n startH = height;\n const onMove = (ev) => {\n const newH = Math.max(16, startH + ev.clientY - startY);\n node.style.height = newH + 'px';\n block.attrs = block.attrs || {};\n block.attrs.height = newH;\n };\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n node.appendChild(handle);\n return node;\n }\n\n _renderColumns(block) {\n const numCols = block.attrs?.columns || 2;\n const node = el('div', { className: 'fe-block-columns' });\n for (let i = 0; i < numCols; i++) {\n const col = el('div', {\n className: 'fe-column',\n contentEditable: 'true',\n dataset: { placeholder: `Column ${i + 1}` },\n innerHTML: block.attrs?.[`col${i}`] || '',\n });\n col.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs[`col${i}`] = col.innerHTML;\n });\n node.appendChild(col);\n }\n\n const controls = el('div', { className: 'fe-columns-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.columns = Math.max(1, Number(block.attrs.columns || numCols) + 1);\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '- Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n const current = Math.max(1, Number(block.attrs.columns || numCols));\n if (current <= 1) return;\n delete block.attrs[`col${current - 1}`];\n block.attrs.columns = current - 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n _renderTable(block) {\n const rows = block.attrs?.rows || 3;\n const cols = block.attrs?.cols || 3;\n const node = el('div', { className: 'fe-block-table' });\n const table = el('table');\n const data = block.attrs?.data || [];\n\n for (let r = 0; r < rows; r++) {\n const tr = el('tr');\n for (let c = 0; c < cols; c++) {\n const cellTag = r === 0 ? 'th' : 'td';\n const cell = el(cellTag, {\n contentEditable: 'true',\n innerHTML: data[r]?.[c] || '',\n });\n cell.addEventListener('input', () => {\n if (!block.attrs) block.attrs = {};\n if (!block.attrs.data) block.attrs.data = [];\n if (!block.attrs.data[r]) block.attrs.data[r] = [];\n block.attrs.data[r][c] = cell.innerHTML;\n });\n tr.appendChild(cell);\n }\n table.appendChild(tr);\n }\n\n node.appendChild(table);\n\n // Add row/column buttons\n const controls = el('div', { className: 'fe-table-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Row',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.rows = (block.attrs.rows || 3) + 1;\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.cols = (block.attrs.cols || 3) + 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n /* ---- Upload Helpers ---- */\n\n async _handleMediaUpload(block) {\n let accept = '*/*';\n if (block.type === 'image' || block.type === 'gallery') accept = 'image/*';\n else if (block.type === 'video') accept = 'video/*';\n else if (block.type === 'audio') accept = 'audio/*';\n\n const multiple = block.type === 'gallery';\n const files = await this.editor.mediaUploader.openFilePicker(accept, multiple);\n if (files.length === 0) return;\n\n if (block.type === 'gallery') {\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n block.content = result.remoteUrl || result.localUrl;\n if (block.type === 'file') {\n block.attrs = block.attrs || {};\n block.attrs.filename = files[0].name;\n block.attrs.filesize = _formatSize(files[0].size);\n }\n }\n }\n this.editor.render();\n }\n\n async _triggerImageUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (files.length === 0) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) block.content = result.remoteUrl || result.localUrl;\n this.editor.render();\n }\n\n async _triggerGalleryUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*', true);\n if (files.length === 0) return;\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n this.editor.render();\n }\n\n _setupDropZone(element, block) {\n element.addEventListener('dragover', (e) => {\n e.preventDefault();\n element.classList.add('fe-drop-active');\n });\n element.addEventListener('dragleave', () => {\n element.classList.remove('fe-drop-active');\n });\n element.addEventListener('drop', async (e) => {\n e.preventDefault();\n element.classList.remove('fe-drop-active');\n const results = await this.editor.mediaUploader.handleDrop(e.dataTransfer);\n if (results && results.length > 0) {\n if (block.type === 'gallery') {\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const res = results[0];\n if (!res.error) block.content = res.remoteUrl || res.localUrl;\n }\n this.editor.render();\n }\n });\n }\n\n /* ---- Content Events ---- */\n\n _bindContentEvents(node, block) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n\n // Helper to update empty state\n const updateEmptyState = () => {\n const text = node.textContent || '';\n const isEmpty = isRawTextBlock\n ? text.trim() === ''\n : text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '');\n node.dataset.empty = isEmpty ? 'true' : 'false';\n };\n\n // Update empty state initially\n updateEmptyState();\n\n // Ensure contenteditable gets focus when clicked\n node.addEventListener('mousedown', (e) => {\n // Let wrapper click handle first-time block selection to avoid losing focus on re-render\n if (this.editor._selectedBlockId !== block.id) return;\n // Stop propagation so wrapper click does not override caret placement on selected blocks\n e.stopPropagation();\n // Immediately focus on mousedown for better responsiveness\n if (document.activeElement !== node) {\n node.focus();\n // If empty (only has <br>), place caret correctly\n const text = node.textContent || '';\n if (text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '')) {\n // Ensure there's a <br> for cursor visibility\n if (node.innerHTML.trim() === '') {\n node.innerHTML = '<br>';\n }\n // Place caret after the <br>\n setTimeout(() => {\n const range = document.createRange();\n const sel = window.getSelection();\n range.selectNodeContents(node);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }, 0);\n }\n }\n });\n\n node.addEventListener('input', () => {\n if (isRawTextBlock) {\n block.content = node.textContent || '';\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n return;\n }\n\n // Clean up: if content is just <br> or empty, store as empty string\n let content = node.innerHTML.trim();\n if (content === '<br>' || content === '<br/>' || content === '') {\n content = '';\n // Keep the <br> in the DOM for cursor visibility, but don't save it\n if (!node.querySelector('br')) {\n node.innerHTML = '<br>';\n }\n }\n block.content = content;\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n });\n\n node.addEventListener('keydown', (e) => {\n this.editor._onBlockKeydown(e, block, node);\n });\n\n node.addEventListener('focus', () => {\n this.editor.selectBlock(block.id);\n });\n\n node.addEventListener('paste', (e) => {\n // Code blocks: plain text only\n if (block.type === 'code' || block.type === 'html') {\n e.preventDefault();\n const text = e.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n return;\n }\n\n // Image paste\n if (e.clipboardData.items) {\n const imageItems = [...e.clipboardData.items].filter((i) => i.type.startsWith('image/'));\n if (imageItems.length > 0) {\n e.preventDefault();\n this.editor.mediaUploader.handlePaste(e.clipboardData).then((results) => {\n if (results && results.length > 0) {\n const src = results[0].remoteUrl || results[0].localUrl;\n if (src) {\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n }\n }\n });\n return;\n }\n }\n });\n }\n}\n\nfunction _formatSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n}\n\nfunction _normalizeImageWidth(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return 100;\n return Math.max(10, Math.min(100, Math.round(numeric)));\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Top editor header bar: inserter button, undo/redo, status, save/publish, settings toggle.\n */\nexport class Header {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-header' });\n\n // Left\n const left = el('div', { className: 'fe-header-left' });\n\n // Block inserter toggle\n const inserterBtn = el('button', {\n className: 'fe-inserter-toggle',\n innerHTML: icons.plus,\n title: 'Toggle block inserter',\n onClick: (e) => this.editor.inserterPanel.toggle(e.currentTarget),\n });\n left.appendChild(inserterBtn);\n left.appendChild(el('span', { className: 'fe-sep' }));\n\n // Undo / Redo\n left.appendChild(this._iconBtn(icons.undo, 'Undo (Ctrl+Z)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.undo({ preferNative: inEditable });\n }));\n left.appendChild(this._iconBtn(icons.redo, 'Redo (Ctrl+Y)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.redo({ preferNative: inEditable });\n }));\n this.el.appendChild(left);\n\n // Center spacer\n const center = el('div', { className: 'fe-header-center' });\n this.el.appendChild(center);\n\n // Right\n const right = el('div', { className: 'fe-header-right' });\n\n if (this.editor.options.showHeaderActions) {\n const draftBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Save draft',\n onClick: () => this.editor.save(),\n });\n right.appendChild(draftBtn);\n\n const publishBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Publish',\n onClick: () => this.editor.publish(),\n });\n right.appendChild(publishBtn);\n }\n\n if (this.editor.options.showSettingsPanel) {\n if (right.childNodes.length > 0) {\n right.appendChild(el('span', { className: 'fe-sep' }));\n }\n right.appendChild(this._iconBtn(icons.settings, 'Settings', () => {\n this.editor.settingsPanel.toggle();\n this.editor._updateCanvasMargin();\n }));\n }\n\n this.el.appendChild(right);\n return this.el;\n }\n\n setStatus(text, color) {\n // no-op: status text removed from header UI\n }\n\n _iconBtn(iconHTML, title, onClick) {\n return el('button', {\n className: 'fe-icon-btn',\n innerHTML: iconHTML,\n title,\n onClick,\n });\n }\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Floating block toolbar for formatting and block controls.\n */\nexport class Toolbar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._linkPopover = null;\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n this._statefulButtons = [];\n this._savedLinkRange = null;\n this._tableToolsSep = null;\n this._tableRowBtn = null;\n this._tableColBtn = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-block-toolbar' });\n this._linkPopover = this._createLinkPopover();\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n return this.el;\n }\n\n show(blockId) {\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) return this.hide();\n const getActiveBlockId = () => this.editor._selectedBlockId || blockId;\n\n this.el.innerHTML = '';\n this.el.classList.add('fe-visible');\n this._statefulButtons = [];\n\n // Drag handle — lets user reposition the toolbar\n const dragBtn = this._addBtn(icons.dragHandle, 'Drag toolbar', null, 'fe-tb-drag');\n this._initToolbarDrag(dragBtn);\n\n this._addSep();\n\n // Move buttons\n this._addBtn(icons.arrowUp, 'Move up', () => this.editor.blockManager.moveBlock(blockId, -1));\n this._addBtn(icons.arrowDown, 'Move down', () => this.editor.blockManager.moveBlock(blockId, 1));\n\n this._addSep();\n\n // Type-specific tools\n const type = block.type;\n const textTypes = ['paragraph', 'heading', 'heading-3', 'heading-4', 'quote', 'pullquote', 'list', 'ordered-list'];\n const htmlEditableTypes = [...textTypes, 'code', 'html'];\n\n if (textTypes.includes(type)) {\n // Block type selector\n const select = el('select', { className: 'fe-tb-select' });\n const options = [\n { value: 'paragraph', label: 'Paragraph' },\n { value: 'heading', label: 'Heading 2' },\n { value: 'heading-3', label: 'Heading 3' },\n { value: 'heading-4', label: 'Heading 4' },\n { value: 'quote', label: 'Quote' },\n { value: 'list', label: 'Bullet List' },\n { value: 'ordered-list', label: 'Numbered List' },\n { value: 'code', label: 'Code' },\n ];\n options.forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n if (opt.value === type) o.selected = true;\n select.appendChild(o);\n });\n select.addEventListener('change', () => {\n const value = select.value;\n const blockNow = this.editor.blockManager.getBlock(blockId);\n if (!blockNow) return;\n\n const ensureParagraphContext = () => {\n if (blockNow.type !== 'paragraph') {\n this.editor.blockManager.changeBlockType(blockId, 'paragraph');\n this.editor.render();\n }\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.focus();\n return contentEl;\n };\n\n if (value === 'paragraph' || value === 'heading' || value === 'heading-3' || value === 'heading-4' || value === 'quote') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n const tag = value === 'paragraph'\n ? 'P'\n : value === 'heading'\n ? 'H2'\n : value === 'heading-3'\n ? 'H3'\n : value === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (value === 'list' || value === 'ordered-list') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n document.execCommand(value === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n this.editor.blockManager.changeBlockType(blockId, value);\n this.editor.render();\n this.editor.focusBlock(blockId);\n return;\n }\n\n this.editor.blockManager.changeBlockType(blockId, value);\n this.editor.render();\n this.editor.focusBlock(blockId);\n });\n this.el.appendChild(select);\n\n this._addSep();\n\n // Font size\n const fontSizeSelect = el('select', { className: 'fe-tb-select', title: 'Font size' });\n [\n { value: '', label: 'Size' },\n { value: '13', label: '13px' },\n { value: '16', label: '16px' },\n { value: '20', label: '20px' },\n { value: '28', label: '28px' },\n { value: '36', label: '36px' },\n ].forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n fontSizeSelect.appendChild(o);\n });\n fontSizeSelect.addEventListener('change', () => {\n if (!fontSizeSelect.value) return;\n this._applyFontSize(fontSizeSelect.value);\n this._syncFontSizeSelect();\n });\n this.el.appendChild(fontSizeSelect);\n this._fontSizeSelect = fontSizeSelect;\n this._bindFontSizeTracking();\n this._syncFontSizeSelect();\n\n this._addSep();\n\n // Formatting\n this._addStatefulBtn('bold', icons.bold, 'Bold (Ctrl+B)', () => this._exec('bold'));\n this._addStatefulBtn('italic', icons.italic, 'Italic (Ctrl+I)', () => this._exec('italic'));\n this._addStatefulBtn('underline', icons.underline, 'Underline (Ctrl+U)', () => this._exec('underline'));\n this._addStatefulBtn('strikeThrough', icons.strikethrough, 'Strikethrough', () => this._exec('strikeThrough'));\n this._addBtn(icons.inlineCode, 'Inline Code', () => this._wrapInlineCode());\n this._addStatefulBtn('link', icons.link, 'Link (Ctrl+K)', () => this._showLinkPopover());\n\n this._addSep();\n\n // Alignment\n this._addBtn(icons.alignLeft, 'Align Left', () => this._exec('justifyLeft'));\n this._addBtn(icons.alignCenter, 'Align Center', () => this._exec('justifyCenter'));\n this._addBtn(icons.alignRight, 'Align Right', () => this._exec('justifyRight'));\n\n this._tableToolsSep = this._addSep();\n this._tableRowBtn = this._addTextBtn('+Row', 'Add table row', () => this._addTableRow());\n this._tableColBtn = this._addTextBtn('+Col', 'Add table column', () => this._addTableColumn());\n }\n\n if (htmlEditableTypes.includes(type)) {\n this._addSep();\n this._addBtn(\n icons.html,\n type === 'html' ? 'Switch to normal text mode' : 'Switch to HTML mode',\n () => this.editor.toggleBlockHtmlMode(getActiveBlockId()),\n type === 'html' ? 'active' : ''\n );\n }\n\n this._syncStatefulButtons();\n\n this._addSep();\n\n // Duplicate & Delete\n this._addBtn(icons.file, 'Duplicate', () => {\n const clone = this.editor.blockManager.duplicateBlock(getActiveBlockId());\n if (clone) this.editor.render();\n });\n this._addBtn(icons.trash, 'Delete', () => {\n const activeId = getActiveBlockId();\n const removed = this.editor.blockManager.removeBlock(activeId);\n if (removed) {\n this.editor.render();\n return;\n }\n\n // If only one block remains, make delete behave like \"clear block\".\n const blockToClear = this.editor.blockManager.getBlock(activeId);\n if (!blockToClear) return;\n blockToClear.type = 'paragraph';\n blockToClear.content = '';\n blockToClear.attrs = {};\n this.editor.render();\n this.editor.focusBlock(activeId);\n }, 'fe-tb-btn-danger');\n }\n\n hide() {\n if (this.el) this.el.classList.remove('fe-visible');\n this._hideLinkPopover();\n this._unbindFontSizeTracking();\n }\n\n /* ---- Private ---- */\n\n _initToolbarDrag(handle) {\n let startX, startY, origLeft, origTop, dragging = false;\n\n const onMouseMove = (e) => {\n if (!dragging) return;\n const dx = e.clientX - startX;\n const dy = e.clientY - startY;\n this.el.style.left = (origLeft + dx) + 'px';\n this.el.style.top = (origTop + dy) + 'px';\n };\n\n const onMouseUp = () => {\n dragging = false;\n this.el.classList.remove('fe-toolbar-dragging');\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n };\n\n handle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n dragging = true;\n startX = e.clientX;\n startY = e.clientY;\n origLeft = parseInt(this.el.style.left || '0', 10);\n origTop = parseInt(this.el.style.top || '0', 10);\n this.el.classList.add('fe-toolbar-dragging');\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n });\n }\n\n _addBtn(iconHTML, title, onClick, extraClass = '') {\n const btn = el('button', {\n className: `fe-tb-btn ${extraClass}`.trim(),\n type: 'button',\n innerHTML: iconHTML,\n title,\n });\n btn.addEventListener('mousedown', (e) => {\n // Preserve current editor selection for rich-text commands/popovers.\n e.preventDefault();\n e.stopPropagation();\n });\n if (onClick) btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); onClick(); });\n this.el.appendChild(btn);\n return btn;\n }\n\n _addStatefulBtn(command, iconHTML, title, onClick) {\n const btn = this._addBtn(iconHTML, title, onClick);\n this._statefulButtons.push({ command, btn });\n return btn;\n }\n\n _addSep() {\n const sep = el('span', { className: 'fe-tb-sep' });\n this.el.appendChild(sep);\n return sep;\n }\n\n _addTextBtn(label, title, onClick) {\n const btn = el('button', {\n className: 'fe-tb-text-btn',\n type: 'button',\n title,\n innerHTML: label,\n });\n btn.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n });\n this.el.appendChild(btn);\n return btn;\n }\n\n _exec(cmd) {\n document.execCommand(cmd, false, null);\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n }\n\n _wrapInlineCode() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n const code = document.createElement('code');\n code.className = 'fe-inline-code';\n range.surroundContents(code);\n this.editor._syncCurrentBlockContent();\n }\n\n _applyFontSize(px) {\n const size = Number(px);\n if (!Number.isFinite(size)) return;\n\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n\n if (range.collapsed) {\n // Apply style for text typed from the current caret onward only.\n const marker = document.createElement('span');\n marker.style.fontSize = `${size}px`;\n marker.appendChild(document.createTextNode('\\u200B'));\n range.insertNode(marker);\n\n const nextRange = document.createRange();\n nextRange.setStart(marker.firstChild, 1);\n nextRange.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n const span = document.createElement('span');\n span.style.fontSize = `${size}px`;\n span.appendChild(range.extractContents());\n range.insertNode(span);\n\n const nextRange = document.createRange();\n nextRange.selectNodeContents(span);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n this.editor._syncCurrentBlockContent();\n }\n\n _bindFontSizeTracking() {\n if (!this._fontSizeSelect || this._onSelectionChange) return;\n this._onSelectionChange = () => {\n this._syncFontSizeSelect();\n this._syncStatefulButtons();\n };\n document.addEventListener('selectionchange', this._onSelectionChange);\n }\n\n _unbindFontSizeTracking() {\n if (!this._onSelectionChange) return;\n document.removeEventListener('selectionchange', this._onSelectionChange);\n this._onSelectionChange = null;\n }\n\n _syncFontSizeSelect() {\n if (!this._fontSizeSelect) return;\n const px = this._currentSelectionFontSizePx();\n if (!px) {\n this._fontSizeSelect.value = '';\n return;\n }\n const snapped = _closestFontSize(px, [13, 16, 20, 28, 36]);\n this._fontSizeSelect.value = String(snapped);\n }\n\n _currentSelectionFontSizePx() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const node = sel.focusNode;\n if (!node) return null;\n const elNode = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!elNode) return null;\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper || !wrapper.contains(elNode)) return null;\n const raw = window.getComputedStyle(elNode).fontSize;\n const px = Number.parseFloat(raw || '');\n return Number.isFinite(px) ? px : null;\n }\n\n _createLinkPopover() {\n const pop = el('div', { className: 'fe-link-popover' });\n const input = el('input', { type: 'text', placeholder: 'Paste URL or search...', className: 'fe-link-input' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary fe-btn-sm',\n innerHTML: 'Apply',\n });\n const removeBtn = el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: 'Remove',\n });\n\n applyBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n if (input.value) {\n document.execCommand('createLink', false, input.value);\n // Style links\n const wrapper = this.editor._getSelectedBlockEl();\n if (wrapper) {\n wrapper.querySelectorAll('a').forEach((a) => {\n a.classList.add('fe-link');\n a.target = '_blank';\n a.rel = 'noopener';\n });\n }\n }\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n removeBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n document.execCommand('unlink', false, null);\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (e.key === 'Escape') this._hideLinkPopover();\n });\n\n pop.appendChild(input);\n pop.appendChild(applyBtn);\n pop.appendChild(removeBtn);\n return pop;\n }\n\n _showLinkPopover() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n this._savedLinkRange = range.cloneRange();\n const rect = range.getBoundingClientRect();\n const wrapper = this.el.parentElement;\n if (!wrapper) return;\n\n if (!this._linkPopover.parentElement) {\n wrapper.appendChild(this._linkPopover);\n }\n\n this._linkPopover.style.top = (rect.bottom - wrapper.getBoundingClientRect().top + 6) + 'px';\n this._linkPopover.style.left = '0px';\n this._linkPopover.classList.add('fe-open');\n\n // Pre-fill if there's an existing link\n const anchor = sel.anchorNode?.parentElement?.closest('a');\n const input = this._linkPopover.querySelector('input');\n input.value = anchor ? anchor.href : '';\n setTimeout(() => input.focus(), 10);\n }\n\n _hideLinkPopover() {\n if (this._linkPopover) this._linkPopover.classList.remove('fe-open');\n }\n\n _getCurrentTableContext() {\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper) return null;\n const contentEl = wrapper.querySelector('.fe-block-content');\n if (!contentEl) return null;\n\n const sel = window.getSelection();\n let cell = null;\n if (sel && sel.rangeCount > 0) {\n let node = sel.anchorNode;\n if (node && node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (node && typeof node.closest === 'function') {\n const maybeCell = node.closest('td,th');\n if (maybeCell && contentEl.contains(maybeCell)) cell = maybeCell;\n }\n }\n\n const table = cell ? cell.closest('table') : contentEl.querySelector('table');\n if (!table) return null;\n if (!cell) cell = table.querySelector('td,th');\n if (!cell) return null;\n return { table, cell };\n }\n\n _addTableRow() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const rowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n if (currentRow.nextSibling) currentRow.parentNode.insertBefore(newRow, currentRow.nextSibling);\n else currentRow.parentNode.appendChild(newRow);\n\n const range = document.createRange();\n range.selectNodeContents(newRow.querySelector('td'));\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n this.editor._syncCurrentBlockContent();\n }\n\n _addTableColumn() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const idx = Array.from(currentRow.querySelectorAll('th,td')).indexOf(cell);\n if (idx < 0) return;\n\n const rows = Array.from(table.querySelectorAll('tr'));\n rows.forEach((row) => {\n const cells = Array.from(row.querySelectorAll('th,td'));\n const ref = cells[Math.min(idx, cells.length - 1)];\n const newCell = document.createElement(ref && ref.tagName.toLowerCase() === 'th' ? 'th' : 'td');\n newCell.innerHTML = '<br>';\n if (ref && ref.nextSibling) row.insertBefore(newCell, ref.nextSibling);\n else row.appendChild(newCell);\n });\n\n const targetRowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const focusCell = targetRowCells[Math.min(idx + 1, targetRowCells.length - 1)];\n if (focusCell) {\n const range = document.createRange();\n range.selectNodeContents(focusCell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n this.editor._syncCurrentBlockContent();\n }\n\n _restoreSavedLinkRange() {\n if (!this._savedLinkRange) return;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedLinkRange);\n }\n\n _syncStatefulButtons() {\n const wrapper = this.editor._getSelectedBlockEl();\n const sel = window.getSelection();\n const anchor = sel?.anchorNode?.parentElement?.closest('a');\n const hasSelectionInEditor =\n wrapper &&\n sel &&\n sel.rangeCount > 0 &&\n wrapper.contains(sel.anchorNode);\n\n this._statefulButtons.forEach(({ command, btn }) => {\n let active = false;\n if (hasSelectionInEditor) {\n if (command === 'link') {\n active = Boolean(anchor && wrapper.contains(anchor));\n } else {\n try {\n active = document.queryCommandState(command);\n } catch {\n active = false;\n }\n }\n }\n btn.classList.toggle('active', Boolean(active));\n });\n\n const inTable = this._isSelectionInTable(wrapper);\n const tableDisplay = inTable ? '' : 'none';\n if (this._tableToolsSep) this._tableToolsSep.style.display = tableDisplay;\n if (this._tableRowBtn) this._tableRowBtn.style.display = tableDisplay;\n if (this._tableColBtn) this._tableColBtn.style.display = tableDisplay;\n }\n\n _isSelectionInTable(wrapper) {\n if (!wrapper) return false;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let node = sel.anchorNode;\n if (!node) return false;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return false;\n const table = node.closest('table');\n return Boolean(table && wrapper.contains(table));\n }\n}\n\nfunction _closestFontSize(value, sizes) {\n let best = sizes[0];\n let bestDelta = Math.abs(value - best);\n for (let i = 1; i < sizes.length; i++) {\n const delta = Math.abs(value - sizes[i]);\n if (delta < bestDelta) {\n best = sizes[i];\n bestDelta = delta;\n }\n }\n return best;\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { CATEGORIES, getBlocksByCategory, searchBlocks } from '../blocks/registry.js';\n\n/**\n * Side panel for browsing and inserting block types.\n */\nexport class InserterPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._searchInput = null;\n this._listEl = null;\n this._anchorEl = null;\n this._onDocMouseDown = null;\n this._onDocKeyDown = null;\n this._savedRange = null;\n this._mediaModal = null;\n this._mediaModalCard = null;\n this._mediaModalTitle = null;\n this._mediaModalBody = null;\n this._mediaModalResolver = null;\n this._forceNewBlock = false;\n }\n\n create() {\n this.el = el('div', { className: 'fe-inserter-panel' });\n\n // Header\n const header = el('div', { className: 'fe-inserter-header' });\n header.appendChild(el('h3', {}, ['Blocks']));\n const closeBtn = el('button', {\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this.close(),\n });\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n // Search\n this._searchInput = el('input', {\n type: 'text',\n className: 'fe-inserter-search',\n placeholder: 'Search blocks...',\n });\n this._searchInput.addEventListener('input', () => this._renderList());\n this.el.appendChild(this._searchInput);\n\n // List\n this._listEl = el('div', { className: 'fe-inserter-list' });\n this.el.appendChild(this._listEl);\n\n this._renderList();\n this._createMediaModal();\n return this.el;\n }\n\n open(anchorEl = null, options = {}) {\n this._anchorEl = anchorEl || this._anchorEl;\n this._forceNewBlock = Boolean(options.forceNewBlock);\n this._savedRange = this._captureSelectionRange();\n this._positionNearAnchor();\n this.el.classList.add('fe-open');\n this._searchInput.value = '';\n this._renderList();\n this._bindGlobalCloseHandlers();\n setTimeout(() => this._searchInput.focus(), 20);\n }\n\n close() {\n this.el.classList.remove('fe-open');\n this._forceNewBlock = false;\n this._unbindGlobalCloseHandlers();\n }\n\n toggle(anchorEl = null, options = {}) {\n if (anchorEl) this._anchorEl = anchorEl;\n this.el.classList.contains('fe-open') ? this.close() : this.open(anchorEl, options);\n }\n\n isOpen() {\n return this.el.classList.contains('fe-open');\n }\n\n _renderList() {\n this._listEl.innerHTML = '';\n const query = this._searchInput?.value?.trim() || '';\n\n if (query) {\n const results = searchBlocks(query);\n if (results.length === 0) {\n this._listEl.appendChild(el('p', { className: 'fe-inserter-empty' }, ['No blocks found.']));\n return;\n }\n results.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n } else {\n for (const cat of CATEGORIES) {\n const blocks = getBlocksByCategory(cat.id);\n if (blocks.length === 0) continue;\n this._listEl.appendChild(el('div', { className: 'fe-inserter-category' }, [cat.label]));\n blocks.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n }\n }\n }\n\n _createBlockItem(blockDef) {\n const item = el('div', { className: 'fe-inserter-item' });\n item.appendChild(el('div', { className: 'fe-inserter-item-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-inserter-item-info' });\n info.appendChild(el('h4', {}, [blockDef.label]));\n info.appendChild(el('p', {}, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => {\n this._insertFromPopover(blockDef.type);\n this.close();\n });\n\n return item;\n }\n\n _positionNearAnchor() {\n if (!this.el || !this._anchorEl) return;\n const rect = this._anchorEl.getBoundingClientRect();\n const gap = 8;\n const desiredLeft = Math.max(8, Math.min(window.innerWidth - 368, rect.left));\n const desiredTop = Math.max(8, Math.min(window.innerHeight - 520, rect.bottom + gap));\n this.el.style.left = `${desiredLeft}px`;\n this.el.style.top = `${desiredTop}px`;\n }\n\n _bindGlobalCloseHandlers() {\n this._onDocMouseDown = (e) => {\n if (!this.el?.classList.contains('fe-open')) return;\n if (this.el.contains(e.target)) return;\n if (this._anchorEl && this._anchorEl.contains(e.target)) return;\n this.close();\n };\n this._onDocKeyDown = (e) => {\n if (e.key === 'Escape') this.close();\n };\n document.addEventListener('mousedown', this._onDocMouseDown);\n document.addEventListener('keydown', this._onDocKeyDown);\n window.addEventListener('resize', () => this._positionNearAnchor(), { once: true });\n }\n\n _unbindGlobalCloseHandlers() {\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown);\n this._onDocMouseDown = null;\n }\n if (this._onDocKeyDown) {\n document.removeEventListener('keydown', this._onDocKeyDown);\n this._onDocKeyDown = null;\n }\n }\n\n _captureSelectionRange() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n const container = range.commonAncestorContainer;\n if (!this.editor.rootEl.contains(container)) return null;\n return range.cloneRange();\n }\n\n _restoreSelectionRange() {\n if (!this._savedRange) return false;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange);\n return true;\n }\n\n async _insertFromPopover(type) {\n if (this._forceNewBlock) {\n const selectedId = this.editor._selectedBlockId;\n const block = this.editor.blockManager.addBlock(type, {}, selectedId || null);\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n const selectedId = this.editor._selectedBlockId;\n const selectedBlock = selectedId ? this.editor.blockManager.getBlock(selectedId) : null;\n const canInline =\n selectedBlock &&\n selectedBlock.type !== 'code' &&\n selectedBlock.type !== 'html' &&\n selectedBlock.type !== 'image' &&\n selectedBlock.type !== 'gallery' &&\n selectedBlock.type !== 'video' &&\n selectedBlock.type !== 'audio' &&\n selectedBlock.type !== 'file';\n\n if (!canInline) {\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n return;\n }\n\n this._restoreSelectionRange();\n const contentEl = this.editor._getBlockContentEl(selectedId);\n if (contentEl) contentEl.focus();\n\n if (type === 'paragraph' || type === 'heading' || type === 'heading-3' || type === 'heading-4' || type === 'quote') {\n const tag = type === 'paragraph'\n ? 'P'\n : type === 'heading'\n ? 'H2'\n : type === 'heading-3'\n ? 'H3'\n : type === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'list' || type === 'ordered-list') {\n document.execCommand(type === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'image') {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (!files.length) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n const src = result.remoteUrl || result.localUrl;\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n this.editor._syncCurrentBlockContent();\n }\n return;\n }\n\n if (type === 'video' || type === 'audio') {\n const source = await this._chooseMediaSource(type);\n if (!source) return;\n\n if (source === 'url') {\n const url = await this._promptForMediaUrl(type);\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${trimmed}\"></video><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${trimmed}\"></audio><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n }\n\n if (type === 'video' || type === 'audio' || type === 'file') {\n const accept = type === 'video' ? 'video/*' : type === 'audio' ? 'audio/*' : '*/*';\n const files = await this.editor.mediaUploader.openFilePicker(accept);\n if (!files.length) return;\n const file = files[0];\n const result = await this.editor.mediaUploader.processFile(file);\n if (result.error) {\n if (typeof this.editor._showToast === 'function') this.editor._showToast(result.error);\n return;\n }\n const src = result.remoteUrl || result.localUrl;\n if (!src) return;\n\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`);\n } else if (type === 'audio') {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<p><a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${file.name || 'Download file'}</a></p><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'embed') {\n const url = window.prompt('Paste embed URL');\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n document.execCommand('insertHTML', false, `<p><a href=\"${trimmed}\" target=\"_blank\" rel=\"noopener\">${trimmed}</a></p><p><br></p>`);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n }\n\n async _chooseMediaSource(type) {\n if (typeof this.editor.options.onChooseMediaSource === 'function') {\n const selected = await this.editor.options.onChooseMediaSource(type);\n if (selected === 'url' || selected === 'upload') return selected;\n }\n return this._openMediaSourceModal(type);\n }\n\n _createMediaModal() {\n const overlay = el('div', { className: 'fe-media-modal-overlay' });\n const card = el('div', { className: 'fe-media-modal-card' });\n const title = el('h3', { className: 'fe-media-modal-title' }, ['Insert media']);\n const body = el('div', { className: 'fe-media-modal-body' });\n\n card.appendChild(title);\n card.appendChild(body);\n overlay.appendChild(card);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeMediaModal(null);\n });\n\n this.editor.rootEl.appendChild(overlay);\n this._mediaModal = overlay;\n this._mediaModalCard = card;\n this._mediaModalTitle = title;\n this._mediaModalBody = body;\n }\n\n _openMediaSourceModal(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `Insert ${type}`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Choose how you want to add media']);\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Upload File',\n onClick: () => this._closeMediaModal('upload'),\n });\n const urlBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n type: 'button',\n innerHTML: 'Use URL',\n onClick: () => this._closeMediaModal('url'),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n actions.appendChild(uploadBtn);\n actions.appendChild(urlBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(actions);\n\n this._mediaModal.classList.add('fe-open');\n });\n }\n\n _promptForMediaUrl(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `${type} URL`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Paste a direct media URL']);\n const input = el('input', {\n type: 'url',\n className: 'fe-media-modal-input',\n placeholder: `https://example.com/${type}.mp4`,\n });\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Insert',\n onClick: () => this._closeMediaModal(input.value || null),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._closeMediaModal(input.value || null);\n }\n if (e.key === 'Escape') this._closeMediaModal(null);\n });\n\n actions.appendChild(applyBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(input);\n this._mediaModalBody.appendChild(actions);\n this._mediaModal.classList.add('fe-open');\n setTimeout(() => input.focus(), 0);\n });\n }\n\n _closeMediaModal(value) {\n if (!this._mediaModal) return;\n this._mediaModal.classList.remove('fe-open');\n const resolver = this._mediaModalResolver;\n this._mediaModalResolver = null;\n if (resolver) resolver(value);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Right-hand settings panel with Post and Block tabs.\n */\nexport class SettingsPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._activeTab = 'post';\n this._postTab = null;\n this._blockTab = null;\n this._tagInput = null;\n this._tags = [];\n this._categories = ['Uncategorized', 'Technology', 'Design', 'Business', 'Lifestyle'];\n this._featuredImage = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-settings-panel' });\n\n // Tabs\n const tabs = el('div', { className: 'fe-panel-tabs' });\n this._postTabBtn = el('button', { className: 'fe-panel-tab fe-active' }, ['Post']);\n this._blockTabBtn = el('button', { className: 'fe-panel-tab' }, ['Block']);\n this._postTabBtn.addEventListener('click', () => this._switchTab('post'));\n this._blockTabBtn.addEventListener('click', () => this._switchTab('block'));\n tabs.appendChild(this._postTabBtn);\n tabs.appendChild(this._blockTabBtn);\n this.el.appendChild(tabs);\n\n // Post tab content\n this._postTab = el('div', { className: 'fe-tab-content' });\n this._buildPostTab();\n this.el.appendChild(this._postTab);\n\n // Block tab content\n this._blockTab = el('div', { className: 'fe-tab-content', style: { display: 'none' } });\n this._buildBlockTab();\n this.el.appendChild(this._blockTab);\n\n return this.el;\n }\n\n open() { this.el.classList.add('fe-open'); }\n close() { this.el.classList.remove('fe-open'); }\n toggle() { this.el.classList.contains('fe-open') ? this.close() : this.open(); }\n isOpen() { return this.el.classList.contains('fe-open'); }\n\n updateBlockSettings(blockId) {\n this._blockSettingsContent.innerHTML = '';\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) {\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n return;\n }\n\n // Typography\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Typography']));\n\n // Font size\n section.appendChild(el('label', {}, ['Font size']));\n const fontSelect = el('select', { className: 'fe-input' });\n [{ v: '', l: 'Default' }, { v: '13px', l: 'Small' }, { v: '16px', l: 'Medium' }, { v: '20px', l: 'Large' }, { v: '28px', l: 'Extra Large' }, { v: '36px', l: 'Huge' }]\n .forEach(({ v, l }) => fontSelect.appendChild(el('option', { value: v }, [l])));\n fontSelect.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.fontSize = fontSelect.value;\n });\n section.appendChild(fontSelect);\n\n // Line height\n section.appendChild(el('label', {}, ['Line height']));\n const lhInput = el('input', { type: 'text', className: 'fe-input', placeholder: '1.7' });\n lhInput.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl && lhInput.value) contentEl.style.lineHeight = lhInput.value;\n });\n section.appendChild(lhInput);\n\n this._blockSettingsContent.appendChild(section);\n\n // Color\n const colorSection = el('div', { className: 'fe-panel-section' });\n colorSection.appendChild(el('h3', { className: 'fe-section-title' }, ['Color']));\n\n // Text colors\n colorSection.appendChild(el('label', {}, ['Text color']));\n const textColors = el('div', { className: 'fe-color-grid' });\n ['#1e1e1e', '#cf2e2e', '#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#0693e3', '#9b51e0'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.color = c;\n });\n textColors.appendChild(swatch);\n });\n colorSection.appendChild(textColors);\n\n // BG colors\n colorSection.appendChild(el('label', {}, ['Background color']));\n const bgColors = el('div', { className: 'fe-color-grid' });\n ['transparent', '#fcf0f0', '#fef8ee', '#fefce8', '#edf7f2', '#eef6fc', '#f3eafa', '#f0f0f1'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c === 'transparent' ? '#fff' : c, border: c === 'transparent' ? '2px solid #ddd' : 'none' } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.background = c;\n });\n bgColors.appendChild(swatch);\n });\n colorSection.appendChild(bgColors);\n\n this._blockSettingsContent.appendChild(colorSection);\n }\n\n _switchTab(tab) {\n this._activeTab = tab;\n this._postTabBtn.classList.toggle('fe-active', tab === 'post');\n this._blockTabBtn.classList.toggle('fe-active', tab === 'block');\n this._postTab.style.display = tab === 'post' ? 'block' : 'none';\n this._blockTab.style.display = tab === 'block' ? 'block' : 'none';\n }\n\n _buildPostTab() {\n // Summary\n const summary = this._section('Summary');\n summary.appendChild(this._field('Visibility', 'select', ['Public', 'Private', 'Password Protected']));\n summary.appendChild(this._field('Publish', 'select', ['Immediately', 'Schedule']));\n summary.appendChild(this._field('URL Slug', 'text', null, 'fe-url-slug'));\n summary.appendChild(this._field('Author', 'select', ['Admin', 'Editor', 'Author']));\n this._postTab.appendChild(summary);\n\n // Categories\n const cats = this._section('Categories');\n const catList = el('div', { className: 'fe-category-list' });\n this._categories.forEach((cat) => {\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox' }));\n label.appendChild(document.createTextNode(' ' + cat));\n catList.appendChild(label);\n });\n cats.appendChild(catList);\n const addCat = el('a', { href: '#', className: 'fe-add-link' }, ['+ Add New Category']);\n addCat.addEventListener('click', (e) => {\n e.preventDefault();\n const name = prompt('Category name:');\n if (name) {\n this._categories.push(name);\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox', checked: true }));\n label.appendChild(document.createTextNode(' ' + name));\n catList.appendChild(label);\n }\n });\n cats.appendChild(addCat);\n this._postTab.appendChild(cats);\n\n // Tags\n const tags = this._section('Tags');\n const tagWrapper = el('div', { className: 'fe-tag-input-wrapper' });\n const tagInput = el('input', { type: 'text', placeholder: 'Add tag...' });\n tagInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault();\n const val = tagInput.value.replace(',', '').trim();\n if (!val) return;\n this._tags.push(val);\n const tag = el('span', { className: 'fe-tag' });\n tag.appendChild(document.createTextNode(val + ' '));\n const remove = el('span', { className: 'fe-tag-remove', innerHTML: '×' });\n remove.addEventListener('click', () => {\n this._tags = this._tags.filter((t) => t !== val);\n tag.remove();\n });\n tag.appendChild(remove);\n tagWrapper.insertBefore(tag, tagInput);\n tagInput.value = '';\n }\n });\n tagWrapper.appendChild(tagInput);\n tagWrapper.addEventListener('click', () => tagInput.focus());\n tags.appendChild(tagWrapper);\n tags.appendChild(el('p', { className: 'fe-hint' }, ['Separate with commas or Enter key']));\n this._postTab.appendChild(tags);\n\n // Featured Image\n const fi = this._section('Featured Image');\n const fiArea = el('div', { className: 'fe-featured-image-area' });\n fiArea.appendChild(el('p', {}, ['Set featured image']));\n const fiInput = el('input', { type: 'file', accept: 'image/*', style: { display: 'none' } });\n fiInput.addEventListener('change', (e) => {\n const file = e.target.files[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (ev) => {\n fiArea.innerHTML = '';\n const img = el('img', { src: ev.target.result });\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n fiArea.appendChild(img);\n this._featuredImage = ev.target.result;\n this.editor.emit('featuredImage:change', this._featuredImage);\n };\n reader.readAsDataURL(file);\n });\n fiArea.addEventListener('click', () => fiInput.click());\n fi.appendChild(fiArea);\n fi.appendChild(fiInput);\n this._postTab.appendChild(fi);\n\n // Excerpt\n const exc = this._section('Excerpt');\n exc.appendChild(el('textarea', { className: 'fe-input fe-textarea', placeholder: 'Write an excerpt (optional)' }));\n this._postTab.appendChild(exc);\n\n // Discussion\n const disc = this._section('Discussion');\n disc.appendChild(this._toggle('Allow comments', true));\n disc.appendChild(this._toggle('Allow pingbacks', false));\n this._postTab.appendChild(disc);\n }\n\n _buildBlockTab() {\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Block Settings']));\n this._blockSettingsContent = el('div');\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n section.appendChild(this._blockSettingsContent);\n this._blockTab.appendChild(section);\n }\n\n _section(title) {\n const s = el('div', { className: 'fe-panel-section' });\n s.appendChild(el('h3', { className: 'fe-section-title' }, [title]));\n return s;\n }\n\n _field(label, type, options, id) {\n const frag = document.createDocumentFragment();\n frag.appendChild(el('label', {}, [label]));\n if (type === 'select') {\n const select = el('select', { className: 'fe-input' });\n if (id) select.id = id;\n (options || []).forEach((o) => select.appendChild(el('option', {}, [o])));\n frag.appendChild(select);\n } else {\n const input = el('input', { type, className: 'fe-input', placeholder: label.toLowerCase() });\n if (id) input.id = id;\n frag.appendChild(input);\n }\n return frag;\n }\n\n _toggle(label, defaultOn) {\n const row = el('div', { className: 'fe-toggle-row' });\n row.appendChild(el('label', {}, [label]));\n const btn = el('button', { className: `fe-toggle-switch ${defaultOn ? 'fe-on' : ''}` });\n btn.addEventListener('click', () => btn.classList.toggle('fe-on'));\n row.appendChild(btn);\n return row;\n }\n}\n","import { el } from '../utils/dom.js';\nimport { searchBlocks, BLOCK_TYPES } from '../blocks/registry.js';\n\n/**\n * Inline slash-command menu that appears when user types \"/\".\n */\nexport class SlashMenu {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._visible = false;\n this._highlightIndex = 0;\n this._items = [];\n this._targetBlock = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-slash-menu' });\n this._boundDocClick = (e) => {\n if (!e.target.closest('.fe-slash-menu')) this.close();\n };\n document.addEventListener('click', this._boundDocClick);\n return this.el;\n }\n\n /** Remove global listeners. Called by editor.destroy(). */\n destroy() {\n if (this._boundDocClick) {\n document.removeEventListener('click', this._boundDocClick);\n this._boundDocClick = null;\n }\n }\n\n open(block, rect) {\n this._targetBlock = block;\n this._visible = true;\n this._highlightIndex = 0;\n this.el.classList.add('fe-open');\n\n // Position near the caret\n const editorRect = this.editor.el.getBoundingClientRect();\n this.el.style.top = (rect.bottom - editorRect.top + 4) + 'px';\n this.el.style.left = (rect.left - editorRect.left) + 'px';\n\n this._filter('');\n }\n\n close() {\n this._visible = false;\n this._targetBlock = null;\n this.el.classList.remove('fe-open');\n }\n\n isOpen() {\n return this._visible;\n }\n\n filter(query) {\n this._filter(query);\n }\n\n handleKeydown(e) {\n if (!this._visible) return false;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._navigate(1);\n return true;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n this._navigate(-1);\n return true;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n if (visible[this._highlightIndex]) {\n this._selectItem(visible[this._highlightIndex].type);\n }\n return true;\n }\n if (e.key === 'Escape') {\n this.close();\n return true;\n }\n return false;\n }\n\n _filter(query) {\n this.el.innerHTML = '';\n this._items = [];\n\n const allBlocks = query ? searchBlocks(query) : Object.entries(BLOCK_TYPES).map(([type, def]) => ({ type, ...def }));\n\n allBlocks.forEach((blockDef, i) => {\n const item = el('div', { className: `fe-slash-item ${i === 0 ? 'fe-highlighted' : ''}` });\n item.appendChild(el('div', { className: 'fe-slash-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-slash-info' });\n info.appendChild(el('div', { className: 'fe-slash-label' }, [blockDef.label]));\n info.appendChild(el('div', { className: 'fe-slash-desc' }, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => this._selectItem(blockDef.type));\n item.addEventListener('mouseenter', () => {\n this.el.querySelectorAll('.fe-slash-item').forEach((el) => el.classList.remove('fe-highlighted'));\n item.classList.add('fe-highlighted');\n });\n\n this.el.appendChild(item);\n this._items.push({ el: item, type: blockDef.type });\n });\n\n if (this._items.length === 0) {\n this.el.appendChild(el('div', { className: 'fe-slash-empty' }, ['No blocks found']));\n }\n\n this._highlightIndex = 0;\n }\n\n _navigate(dir) {\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n visible.forEach((i) => i.el.classList.remove('fe-highlighted'));\n this._highlightIndex = Math.max(0, Math.min(visible.length - 1, this._highlightIndex + dir));\n if (visible[this._highlightIndex]) {\n visible[this._highlightIndex].el.classList.add('fe-highlighted');\n visible[this._highlightIndex].el.scrollIntoView({ block: 'nearest' });\n }\n }\n\n _selectItem(type) {\n if (!this._targetBlock) return;\n const block = this._targetBlock;\n const inserted = this.editor.insertSingleBlockType(type);\n if (inserted) {\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n // Change the block type and clear content\n this.editor.blockManager.changeBlockType(block.id, type);\n block.content = '';\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Bottom status bar showing word count, character count, block count.\n */\nexport class StatusBar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._wordEl = null;\n this._charEl = null;\n this._blockEl = null;\n this._savedEl = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-status-bar' });\n this._wordEl = el('span', {}, ['Words: 0']);\n this._charEl = el('span', {}, ['Characters: 0']);\n this._blockEl = el('span', {}, ['Blocks: 0']);\n this._savedEl = el('span', { className: 'fe-status-right' });\n\n this.el.appendChild(this._wordEl);\n this.el.appendChild(this._charEl);\n this.el.appendChild(this._blockEl);\n this.el.appendChild(this._savedEl);\n\n return this.el;\n }\n\n update() {\n const bm = this.editor.blockManager;\n const titleText = this.editor._titleEl ? this.editor._titleEl.value : '';\n const titleWords = titleText.trim().split(/\\s+/).filter((w) => w.length).length;\n const words = bm.getWordCount() + titleWords;\n const chars = bm.getCharCount() + titleText.replace(/\\s/g, '').length;\n\n this._wordEl.textContent = `Words: ${words}`;\n this._charEl.textContent = `Characters: ${chars}`;\n this._blockEl.textContent = `Blocks: ${bm.blocks.length}`;\n }\n\n setSaved(text) {\n this._savedEl.textContent = text;\n }\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Dynamic plugin and block-type registry.\n *\n * Replaces the old static BLOCK_TYPES object with a dynamic system\n * that supports registering custom block types and plugins at runtime.\n *\n * @example\n * // Register a custom block type\n * editor.registerBlockType('callout', {\n * label: 'Callout',\n * description: 'A highlighted callout box.',\n * icon: '<svg>...</svg>',\n * category: 'design',\n * hasContent: true,\n * contentTag: 'div',\n * placeholder: 'Write callout...',\n * className: 'fe-callout-block',\n * });\n *\n * // Register a plugin (bundles block types + lifecycle hooks)\n * editor.registerPlugin({\n * name: 'my-plugin',\n * version: '1.0.0',\n * blocks: {\n * callout: { label: 'Callout', ... },\n * },\n * init(editor) { ... },\n * destroy() { ... },\n * });\n */\nexport class PluginRegistry extends EventEmitter {\n constructor() {\n super();\n /** @type {Map<string, Object>} Block type definitions keyed by type name */\n this._blockTypes = new Map();\n /** @type {Map<string, Object>} Registered plugins keyed by name */\n this._plugins = new Map();\n /** @type {Array<{id:string,label:string}>} Category list */\n this._categories = [];\n }\n\n /* ---- Block Type Registration ---- */\n\n /**\n * Register a new block type or override an existing one.\n * @param {string} type - Block type identifier (e.g. 'callout').\n * @param {Object} definition - Block type definition.\n * @returns {void}\n */\n registerBlockType(type, definition) {\n if (!type || typeof type !== 'string') {\n throw new Error('PluginRegistry: block type must be a non-empty string.');\n }\n if (!definition || typeof definition !== 'object') {\n throw new Error(`PluginRegistry: definition for \"${type}\" must be an object.`);\n }\n\n const def = {\n label: definition.label || type,\n description: definition.description || '',\n icon: definition.icon || '',\n category: definition.category || 'custom',\n hasContent: definition.hasContent !== false,\n contentTag: definition.contentTag || 'div',\n placeholder: definition.placeholder || '',\n className: definition.className || '',\n isMedia: Boolean(definition.isMedia),\n // Custom renderer (optional) — function(block, editor) => HTMLElement\n render: definition.render || null,\n // Custom HTML serializer (optional) — function(block) => string\n toHTML: definition.toHTML || null,\n // Custom HTML parser (optional) — function(html) => { type, content, attrs }\n fromHTML: definition.fromHTML || null,\n };\n\n const isNew = !this._blockTypes.has(type);\n this._blockTypes.set(type, def);\n\n // Auto-register category if it doesn't exist\n if (def.category && !this._categories.find(c => c.id === def.category)) {\n this._categories.push({ id: def.category, label: _capitalize(def.category) });\n }\n\n this.emit(isNew ? 'blockType:registered' : 'blockType:updated', type, def);\n }\n\n /**\n * Unregister a block type.\n */\n unregisterBlockType(type) {\n if (this._blockTypes.has(type)) {\n this._blockTypes.delete(type);\n this.emit('blockType:unregistered', type);\n }\n }\n\n /**\n * Get a block type definition.\n * @returns {Object|undefined}\n */\n getBlockType(type) {\n return this._blockTypes.get(type);\n }\n\n /**\n * Get all block types as a plain object (for backward compatibility).\n * @returns {Record<string, Object>}\n */\n getAllBlockTypes() {\n const obj = {};\n for (const [type, def] of this._blockTypes) {\n obj[type] = def;\n }\n return obj;\n }\n\n /**\n * Get blocks for a category.\n */\n getBlocksByCategory(catId) {\n const result = [];\n for (const [type, def] of this._blockTypes) {\n if (def.category === catId) result.push({ type, ...def });\n }\n return result;\n }\n\n /**\n * Search blocks by query string.\n */\n searchBlocks(query) {\n const q = query.toLowerCase();\n const result = [];\n for (const [type, def] of this._blockTypes) {\n if (\n type.includes(q) ||\n def.label.toLowerCase().includes(q) ||\n def.description.toLowerCase().includes(q)\n ) {\n result.push({ type, ...def });\n }\n }\n return result;\n }\n\n /**\n * Get registered categories.\n */\n getCategories() {\n return [...this._categories];\n }\n\n /**\n * Register a category.\n */\n registerCategory(id, label) {\n if (!this._categories.find(c => c.id === id)) {\n this._categories.push({ id, label: label || _capitalize(id) });\n this.emit('category:registered', id);\n }\n }\n\n /* ---- Plugin Registration ---- */\n\n /**\n * Register a plugin.\n * @param {Object} plugin - Plugin descriptor.\n * @param {string} plugin.name - Unique plugin name.\n * @param {string} [plugin.version] - Plugin version string.\n * @param {Object} [plugin.blocks] - Block type definitions to register.\n * @param {Function} [plugin.init] - Initialization function, receives editor instance.\n * @param {Function} [plugin.destroy] - Cleanup function.\n */\n registerPlugin(plugin) {\n if (!plugin || !plugin.name) {\n throw new Error('PluginRegistry: plugin must have a name.');\n }\n\n if (this._plugins.has(plugin.name)) {\n console.warn(`PluginRegistry: plugin \"${plugin.name}\" is already registered. Overwriting.`);\n this.unregisterPlugin(plugin.name);\n }\n\n this._plugins.set(plugin.name, plugin);\n\n // Register any block types bundled with the plugin\n if (plugin.blocks && typeof plugin.blocks === 'object') {\n for (const [type, def] of Object.entries(plugin.blocks)) {\n this.registerBlockType(type, { ...def, _plugin: plugin.name });\n }\n }\n\n this.emit('plugin:registered', plugin.name, plugin);\n return plugin;\n }\n\n /**\n * Initialize all registered plugins with the given editor instance.\n */\n initPlugins(editor) {\n for (const [, plugin] of this._plugins) {\n if (typeof plugin.init === 'function') {\n try {\n plugin.init(editor);\n } catch (err) {\n console.error(`PluginRegistry: error initializing plugin \"${plugin.name}\":`, err);\n }\n }\n }\n }\n\n /**\n * Unregister a plugin and its block types.\n */\n unregisterPlugin(name) {\n const plugin = this._plugins.get(name);\n if (!plugin) return;\n\n // Call destroy if available\n if (typeof plugin.destroy === 'function') {\n try { plugin.destroy(); } catch { /* ignore */ }\n }\n\n // Unregister block types that belong to this plugin\n if (plugin.blocks) {\n for (const type of Object.keys(plugin.blocks)) {\n this.unregisterBlockType(type);\n }\n }\n\n this._plugins.delete(name);\n this.emit('plugin:unregistered', name);\n }\n\n /**\n * Get a registered plugin.\n */\n getPlugin(name) {\n return this._plugins.get(name) || null;\n }\n\n /**\n * Get all registered plugin names.\n */\n getPluginNames() {\n return Array.from(this._plugins.keys());\n }\n\n /**\n * Destroy all plugins.\n */\n destroyAll() {\n for (const name of this._plugins.keys()) {\n this.unregisterPlugin(name);\n }\n }\n}\n\nfunction _capitalize(str) {\n if (!str) return '';\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","/**\n * Block-level diff engine for change tracking.\n *\n * Tracks structural and content changes between block snapshots:\n * - Block added / removed / moved\n * - Block content or attributes changed\n *\n * @example\n * const differ = new Differ();\n * differ.setBaseline(blockManager.toJSON());\n * // ... user edits ...\n * const patches = differ.diff(blockManager.toJSON());\n * // => [{ op: 'update', id: 'blk_1', changes: { content: { from: '...', to: '...' } } }]\n */\nexport class Differ {\n constructor() {\n /** @type {Array<Object>|null} Previous snapshot */\n this._baseline = null;\n /** @type {Array<Object>} Accumulated patches since last getChanges() */\n this._pendingPatches = [];\n }\n\n /**\n * Set the baseline snapshot for diffing.\n * @param {Array<Object>} blocks - Array of block objects from toJSON().\n */\n setBaseline(blocks) {\n this._baseline = _deepClone(blocks);\n }\n\n /**\n * Compute diff between baseline and current state.\n * Updates baseline to current state after diffing.\n *\n * @param {Array<Object>} currentBlocks - Current block state.\n * @returns {Array<Object>} Array of patch operations.\n */\n diff(currentBlocks) {\n if (!this._baseline) {\n this._baseline = _deepClone(currentBlocks);\n return [];\n }\n\n const patches = _computeDiff(this._baseline, currentBlocks);\n this._baseline = _deepClone(currentBlocks);\n this._pendingPatches.push(...patches);\n return patches;\n }\n\n /**\n * Get all accumulated patches and clear the buffer.\n * @returns {Array<Object>}\n */\n getChanges() {\n const changes = [...this._pendingPatches];\n this._pendingPatches = [];\n return changes;\n }\n\n /**\n * Check if there are pending changes.\n * @returns {boolean}\n */\n hasChanges() {\n return this._pendingPatches.length > 0;\n }\n\n /**\n * Clear all state.\n */\n reset() {\n this._baseline = null;\n this._pendingPatches = [];\n }\n}\n\n/**\n * Apply an array of patches to a blocks array.\n * @param {Array<Object>} blocks - Original blocks.\n * @param {Array<Object>} patches - Patches to apply.\n * @returns {Array<Object>} New blocks array with patches applied.\n */\nexport function applyPatches(blocks, patches) {\n let result = _deepClone(blocks);\n\n for (const patch of patches) {\n switch (patch.op) {\n case 'add': {\n const newBlock = { ...patch.block };\n if (typeof patch.index === 'number' && patch.index <= result.length) {\n result.splice(patch.index, 0, newBlock);\n } else {\n result.push(newBlock);\n }\n break;\n }\n\n case 'remove': {\n result = result.filter(b => b.id !== patch.id);\n break;\n }\n\n case 'update': {\n const block = result.find(b => b.id === patch.id);\n if (block && patch.changes) {\n for (const [key, change] of Object.entries(patch.changes)) {\n block[key] = change.to;\n }\n }\n break;\n }\n\n case 'move': {\n const fromIdx = result.findIndex(b => b.id === patch.id);\n if (fromIdx !== -1) {\n const [moved] = result.splice(fromIdx, 1);\n result.splice(patch.toIndex, 0, moved);\n }\n break;\n }\n }\n }\n\n return result;\n}\n\n/* ---- Internal ---- */\n\nfunction _computeDiff(oldBlocks, newBlocks) {\n const patches = [];\n const oldMap = new Map(oldBlocks.map(b => [b.id, b]));\n const newMap = new Map(newBlocks.map(b => [b.id, b]));\n\n // Detect removed blocks\n for (const old of oldBlocks) {\n if (!newMap.has(old.id)) {\n patches.push({\n op: 'remove',\n id: old.id,\n block: { ...old },\n });\n }\n }\n\n // Detect added blocks\n for (let i = 0; i < newBlocks.length; i++) {\n const block = newBlocks[i];\n if (!oldMap.has(block.id)) {\n patches.push({\n op: 'add',\n id: block.id,\n index: i,\n block: { ...block },\n });\n }\n }\n\n // Detect updated blocks\n for (const newBlock of newBlocks) {\n const oldBlock = oldMap.get(newBlock.id);\n if (!oldBlock) continue;\n\n const changes = {};\n if (oldBlock.type !== newBlock.type) {\n changes.type = { from: oldBlock.type, to: newBlock.type };\n }\n if (oldBlock.content !== newBlock.content) {\n changes.content = { from: oldBlock.content, to: newBlock.content };\n }\n if (JSON.stringify(oldBlock.attrs) !== JSON.stringify(newBlock.attrs)) {\n changes.attrs = { from: oldBlock.attrs, to: newBlock.attrs };\n }\n\n if (Object.keys(changes).length > 0) {\n patches.push({\n op: 'update',\n id: newBlock.id,\n changes,\n });\n }\n }\n\n // Detect moved blocks (position changes among surviving blocks)\n const survivingOld = oldBlocks.filter(b => newMap.has(b.id)).map(b => b.id);\n const survivingNew = newBlocks.filter(b => oldMap.has(b.id)).map(b => b.id);\n\n if (survivingOld.length === survivingNew.length && survivingOld.length > 0) {\n for (let i = 0; i < survivingOld.length; i++) {\n if (survivingOld[i] !== survivingNew[i]) {\n // Find what moved\n const id = survivingNew[i];\n const oldIdx = survivingOld.indexOf(id);\n if (oldIdx !== i) {\n patches.push({\n op: 'move',\n id,\n fromIndex: oldIdx,\n toIndex: i,\n });\n }\n }\n }\n }\n\n return patches;\n}\n\nfunction _deepClone(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\nimport { Differ, applyPatches } from './Differ.js';\n\n/**\n * Foundation for collaborative editing via WebSocket.\n *\n * Provides block-level synchronization using diffs. Each client\n * sends local changes to a server, which broadcasts them to\n * other clients. Conflicts are resolved at the block level using\n * version numbers.\n *\n * @example\n * const collab = editor.connectCollaborative('wss://my-server.com/doc/123', {\n * userId: 'user_abc',\n * token: 'jwt_...',\n * });\n *\n * collab.on('connected', () => console.log('Connected'));\n * collab.on('remote:change', (patches) => console.log('Remote changes:', patches));\n * collab.on('disconnected', () => console.log('Disconnected'));\n *\n * // Later:\n * collab.disconnect();\n */\nexport class CollaborativeManager extends EventEmitter {\n /**\n * @param {Object} editor - NBDEditor instance.\n * @param {string} wsUrl - WebSocket server URL.\n * @param {Object} [options]\n * @param {string} [options.userId] - Current user identifier.\n * @param {string} [options.token] - Auth token for WebSocket.\n * @param {number} [options.debounceMs=500] - Debounce interval for sending local changes.\n * @param {number} [options.reconnectMs=3000] - Reconnect delay after disconnection.\n * @param {number} [options.maxReconnectAttempts=10] - Max reconnection attempts.\n */\n constructor(editor, wsUrl, options = {}) {\n super();\n this.editor = editor;\n this.wsUrl = wsUrl;\n this.options = {\n userId: options.userId || `user_${Date.now().toString(36)}`,\n token: options.token || null,\n debounceMs: options.debounceMs || 500,\n reconnectMs: options.reconnectMs || 3000,\n maxReconnectAttempts: options.maxReconnectAttempts || 10,\n };\n\n this._ws = null;\n this._differ = new Differ();\n this._connected = false;\n this._reconnectAttempts = 0;\n this._debounceTimer = null;\n this._version = 0;\n this._pendingOps = [];\n this._localChanges = [];\n this._cleanup = null;\n }\n\n /**\n * Connect to the WebSocket server.\n */\n connect() {\n if (this._ws) return;\n\n try {\n const url = new URL(this.wsUrl);\n if (this.options.token) {\n url.searchParams.set('token', this.options.token);\n }\n url.searchParams.set('userId', this.options.userId);\n\n this._ws = new WebSocket(url.toString());\n this._setupWebSocket();\n } catch (err) {\n this.emit('error', err);\n }\n\n // Set baseline for diffing\n this._differ.setBaseline(this.editor.blockManager.toJSON());\n\n // Listen for local changes\n this._cleanup = this.editor.blockManager.on('change', () => {\n this._onLocalChange();\n });\n\n return this;\n }\n\n /**\n * Disconnect from the server.\n */\n disconnect() {\n if (this._debounceTimer) clearTimeout(this._debounceTimer);\n if (this._cleanup) this._cleanup();\n\n if (this._ws) {\n this._ws.onclose = null; // Prevent reconnect\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n\n this._connected = false;\n this._reconnectAttempts = 0;\n this.emit('disconnected');\n }\n\n /**\n * Check if currently connected.\n */\n isConnected() {\n return this._connected;\n }\n\n /**\n * Send a manual sync request to get the latest document state.\n */\n requestSync() {\n this._send({ type: 'sync:request', version: this._version });\n }\n\n /* ---- Internal ---- */\n\n _setupWebSocket() {\n if (!this._ws) return;\n\n this._ws.onopen = () => {\n this._connected = true;\n this._reconnectAttempts = 0;\n this.emit('connected');\n\n // Send join message\n this._send({\n type: 'join',\n userId: this.options.userId,\n version: this._version,\n });\n };\n\n this._ws.onmessage = (event) => {\n try {\n const msg = JSON.parse(event.data);\n this._handleMessage(msg);\n } catch {\n // Ignore malformed messages\n }\n };\n\n this._ws.onclose = (event) => {\n this._connected = false;\n this.emit('disconnected', event.code, event.reason);\n\n // Auto-reconnect\n if (this._reconnectAttempts < this.options.maxReconnectAttempts) {\n this._reconnectAttempts++;\n setTimeout(() => {\n this._ws = null;\n this.connect();\n this.emit('reconnecting', this._reconnectAttempts);\n }, this.options.reconnectMs);\n } else {\n this.emit('reconnect:failed');\n }\n };\n\n this._ws.onerror = (err) => {\n this.emit('error', err);\n };\n }\n\n _handleMessage(msg) {\n switch (msg.type) {\n case 'sync:state': {\n // Full document state from server\n if (Array.isArray(msg.blocks)) {\n this.editor.blockManager.fromJSON(msg.blocks);\n this.editor.render();\n this._differ.setBaseline(msg.blocks);\n this._version = msg.version || 0;\n }\n break;\n }\n\n case 'patches': {\n // Remote patches from another client\n if (msg.userId === this.options.userId) break; // Skip own echoes\n if (!Array.isArray(msg.patches)) break;\n\n const currentBlocks = this.editor.blockManager.toJSON();\n const updatedBlocks = applyPatches(currentBlocks, msg.patches);\n this.editor.blockManager.fromJSON(updatedBlocks);\n this.editor.render();\n this._differ.setBaseline(updatedBlocks);\n this._version = msg.version || this._version + 1;\n\n this.emit('remote:change', msg.patches, msg.userId);\n break;\n }\n\n case 'ack': {\n // Server acknowledged our patches\n this._version = msg.version || this._version;\n this.emit('ack', msg.version);\n break;\n }\n\n case 'error': {\n this.emit('server:error', msg.message);\n break;\n }\n }\n }\n\n _onLocalChange() {\n // Debounce sending changes\n if (this._debounceTimer) clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._sendLocalChanges();\n }, this.options.debounceMs);\n }\n\n _sendLocalChanges() {\n if (!this._connected || !this._ws) return;\n\n const currentBlocks = this.editor.blockManager.toJSON();\n const patches = this._differ.diff(currentBlocks);\n\n if (patches.length === 0) return;\n\n this._send({\n type: 'patches',\n userId: this.options.userId,\n version: this._version,\n patches,\n });\n\n this.emit('local:change', patches);\n }\n\n _send(data) {\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(data));\n }\n }\n}\n","/**\n * HTML sanitization utility.\n *\n * Uses DOMPurify when available; falls back to a simple DOM-based\n * sanitizer that strips <script>, event attributes, and javascript: URIs.\n */\n\nlet _DOMPurify = null;\n\n// Try to load DOMPurify (optional peer dependency)\ntry {\n _DOMPurify = require('isomorphic-dompurify');\n if (_DOMPurify && _DOMPurify.default) _DOMPurify = _DOMPurify.default;\n} catch {\n // DOMPurify not installed — use fallback\n}\n\n/**\n * Default allowed tags and attributes for the editor.\n */\nconst DEFAULT_CONFIG = {\n ALLOWED_TAGS: [\n 'p', 'br', 'b', 'i', 'u', 's', 'em', 'strong', 'a', 'img',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li',\n 'blockquote', 'pre', 'code',\n 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td',\n 'figure', 'figcaption', 'hr',\n 'div', 'span', 'section',\n 'video', 'audio', 'source', 'iframe',\n 'sub', 'sup', 'mark', 'del', 'ins',\n ],\n ALLOWED_ATTR: [\n 'href', 'target', 'rel', 'title',\n 'src', 'alt', 'width', 'height',\n 'class', 'id', 'style',\n 'controls', 'autoplay', 'loop', 'muted', 'preload',\n 'colspan', 'rowspan', 'scope',\n 'border', 'cellpadding', 'cellspacing',\n 'download', 'type',\n 'data-*',\n ],\n ALLOW_DATA_ATTR: true,\n ADD_ATTR: ['target'],\n};\n\n/**\n * Fallback sanitizer when DOMPurify is not available.\n * Uses the browser's DOMParser to strip dangerous content.\n */\nfunction _fallbackSanitize(html, config) {\n if (!html || typeof html !== 'string') return '';\n if (typeof document === 'undefined') return html; // SSR: return as-is\n\n const allowedTags = new Set((config.ALLOWED_TAGS || DEFAULT_CONFIG.ALLOWED_TAGS).map(t => t.toLowerCase()));\n const allowedAttrs = new Set((config.ALLOWED_ATTR || DEFAULT_CONFIG.ALLOWED_ATTR).map(a => a.toLowerCase()));\n const allowDataAttr = config.ALLOW_DATA_ATTR !== false;\n\n const doc = new DOMParser().parseFromString(html, 'text/html');\n const body = doc.body;\n\n // Remove disallowed elements\n const allElements = Array.from(body.querySelectorAll('*'));\n for (const el of allElements) {\n const tag = el.tagName.toLowerCase();\n\n // Remove scripts and dangerous tags entirely\n if (tag === 'script' || tag === 'style' || tag === 'link' || tag === 'meta' || tag === 'noscript') {\n el.remove();\n continue;\n }\n\n // If tag not allowed, unwrap (keep children)\n if (!allowedTags.has(tag)) {\n while (el.firstChild) el.parentNode.insertBefore(el.firstChild, el);\n el.remove();\n continue;\n }\n\n // Remove disallowed attributes\n const attrs = Array.from(el.attributes);\n for (const attr of attrs) {\n const name = attr.name.toLowerCase();\n\n // Always remove event handlers\n if (name.startsWith('on')) {\n el.removeAttribute(attr.name);\n continue;\n }\n\n // Allow data-* attributes if enabled\n if (name.startsWith('data-') && allowDataAttr) continue;\n\n // Check against allowed list\n if (!allowedAttrs.has(name) && !allowedAttrs.has('data-*')) {\n el.removeAttribute(attr.name);\n continue;\n }\n\n // Strip javascript: URIs\n if ((name === 'href' || name === 'src' || name === 'action') &&\n /^\\s*javascript\\s*:/i.test(attr.value)) {\n el.removeAttribute(attr.name);\n }\n }\n }\n\n return body.innerHTML;\n}\n\n/**\n * Create a sanitizer function with the given configuration.\n *\n * @param {Object} [config] - DOMPurify-compatible config overrides.\n * @returns {(html: string) => string} A sanitizer function.\n *\n * @example\n * const sanitize = createSanitizer();\n * sanitize('<p>Hello</p><script>alert(\"xss\")</script>');\n * // => '<p>Hello</p>'\n */\nexport function createSanitizer(config = {}) {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n if (_DOMPurify && typeof _DOMPurify.sanitize === 'function') {\n return function sanitize(html) {\n if (!html || typeof html !== 'string') return '';\n return _DOMPurify.sanitize(html, mergedConfig);\n };\n }\n\n // Fallback\n return function sanitize(html) {\n if (!html || typeof html !== 'string') return '';\n return _fallbackSanitize(html, mergedConfig);\n };\n}\n\n/**\n * Default sanitizer instance with standard editor config.\n */\nexport const sanitize = createSanitizer();\n","/**\n * HTML Normalizer — canonicalizes HTML for consistent round-tripping.\n *\n * Addresses the problem where:\n * editor.setData(html) → editor.toHTML()\n * produces slightly different HTML due to whitespace, attribute ordering,\n * or empty tag differences.\n *\n * @example\n * import { normalizeHTML } from './HtmlNormalizer.js';\n * const canonical = normalizeHTML('<p> Hello </p>');\n * // => '<p>Hello</p>'\n */\n\n/**\n * Normalize an HTML string to a canonical form.\n * @param {string} html - Raw HTML string.\n * @returns {string} Normalized HTML.\n */\nexport function normalizeHTML(html) {\n if (!html || typeof html !== 'string') return '';\n\n // SSR guard\n if (typeof document === 'undefined') return html.trim();\n\n const doc = new DOMParser().parseFromString(`<div>${html}</div>`, 'text/html');\n const container = doc.body.firstChild;\n\n _normalizeNode(container);\n\n return container.innerHTML.trim();\n}\n\n/**\n * Compare two HTML strings for semantic equality.\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function htmlEquals(a, b) {\n return normalizeHTML(a) === normalizeHTML(b);\n}\n\n/* ---- Internal ---- */\n\nfunction _normalizeNode(node) {\n if (!node) return;\n\n // Process children first (bottom-up)\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType === 3) { // TEXT_NODE\n // Collapse internal whitespace (but preserve single spaces)\n let text = child.textContent;\n text = text.replace(/[\\t\\r\\n]+/g, ' '); // tabs/newlines → space\n text = text.replace(/ {2,}/g, ' '); // multiple spaces → single\n child.textContent = text;\n\n // Remove empty text nodes\n if (text.trim() === '' && _isBlockElement(node)) {\n node.removeChild(child);\n }\n } else if (child.nodeType === 1) { // ELEMENT_NODE\n _normalizeElement(child);\n _normalizeNode(child);\n }\n }\n\n // Remove empty inline elements (e.g. <strong></strong>)\n for (const child of Array.from(node.childNodes)) {\n if (child.nodeType === 1 && _isEmptyInline(child)) {\n node.removeChild(child);\n }\n }\n}\n\nfunction _normalizeElement(el) {\n // Sort attributes alphabetically for consistent output\n const attrs = Array.from(el.attributes)\n .sort((a, b) => a.name.localeCompare(b.name));\n\n // Remove and re-add in sorted order\n for (const attr of Array.from(el.attributes)) {\n el.removeAttributeNode(attr);\n }\n for (const attr of attrs) {\n // Normalize attribute values\n let value = attr.value;\n\n // Normalize style attribute\n if (attr.name === 'style') {\n value = _normalizeStyle(value);\n if (!value) continue; // Skip empty styles\n }\n\n // Remove empty class attributes\n if (attr.name === 'class' && !value.trim()) continue;\n\n el.setAttribute(attr.name, value);\n }\n\n // Normalize self-closing tags (img, br, hr, input)\n // (handled by browser serialization already)\n}\n\nfunction _normalizeStyle(style) {\n if (!style || typeof style !== 'string') return '';\n\n return style\n .split(';')\n .map(s => s.trim())\n .filter(Boolean)\n .map(s => {\n const [prop, ...vals] = s.split(':');\n return `${prop.trim().toLowerCase()}:${vals.join(':').trim()}`;\n })\n .sort()\n .join(';');\n}\n\nfunction _isBlockElement(node) {\n if (node.nodeType !== 1) return false;\n const tag = node.tagName.toLowerCase();\n return /^(div|p|h[1-6]|blockquote|pre|ul|ol|li|table|thead|tbody|tr|td|th|figure|figcaption|section|article|main|header|footer|nav|aside|form|fieldset|details|summary|hr)$/.test(tag);\n}\n\nfunction _isEmptyInline(node) {\n if (node.nodeType !== 1) return false;\n const tag = node.tagName.toLowerCase();\n // Don't remove self-closing or semantic elements\n if (/^(br|hr|img|input|video|audio|iframe|source)$/.test(tag)) return false;\n // Check if inline\n if (_isBlockElement(node)) return false;\n // Empty if no text content and no meaningful children\n return node.textContent.trim() === '' && !node.querySelector('img,video,audio,iframe,br');\n}\n","/**\n * Delta-like structured data format for NBDEditor.\n *\n * Provides an opt-in alternative representation alongside HTML.\n * Each block is converted to an array of inline operations (ops),\n * preserving formatting information in a structured way.\n *\n * Format:\n * [\n * {\n * blockId: 'blk_...',\n * blockType: 'paragraph',\n * blockAttrs: {},\n * ops: [\n * { insert: 'Hello ', attrs: {} },\n * { insert: 'world', attrs: { bold: true } },\n * { insert: '\\n', attrs: {} },\n * ]\n * },\n * ...\n * ]\n *\n * @example\n * import { htmlToDelta, deltaToHTML } from './DeltaFormat.js';\n * const delta = blocksToDelta(blocks);\n * const html = deltaToHTML(delta);\n */\n\n/**\n * Convert an array of blocks to Delta format.\n * @param {Array<{id, type, content, attrs}>} blocks\n * @returns {Array<Object>} Delta representation.\n */\nexport function blocksToDelta(blocks) {\n if (!Array.isArray(blocks)) return [];\n return blocks.map((block) => ({\n blockId: block.id,\n blockType: block.type,\n blockAttrs: { ...(block.attrs || {}) },\n ops: _htmlToOps(block.content || '', block.type),\n }));\n}\n\n/**\n * Convert Delta format back to blocks array.\n * @param {Array<Object>} delta\n * @returns {Array<{id, type, content, attrs}>}\n */\nexport function deltaToBlocks(delta) {\n if (!Array.isArray(delta)) return [];\n return delta.map((entry) => ({\n id: entry.blockId,\n type: entry.blockType,\n content: _opsToHTML(entry.ops || [], entry.blockType),\n attrs: { ...(entry.blockAttrs || {}) },\n }));\n}\n\n/**\n * Convert a single HTML string to Delta ops.\n * @param {string} html\n * @param {string} blockType\n * @returns {Array<{insert: string, attrs: Object}>}\n */\nexport function htmlToOps(html, blockType = 'paragraph') {\n return _htmlToOps(html, blockType);\n}\n\n/**\n * Convert Delta ops to HTML string.\n * @param {Array<{insert: string, attrs: Object}>} ops\n * @param {string} blockType\n * @returns {string}\n */\nexport function opsToHTML(ops, blockType = 'paragraph') {\n return _opsToHTML(ops, blockType);\n}\n\n/* ---- Internal Helpers ---- */\n\nfunction _htmlToOps(html, blockType) {\n if (!html || typeof html !== 'string') return [{ insert: '\\n', attrs: {} }];\n\n // For code blocks, treat as plain text\n if (blockType === 'code' || blockType === 'html') {\n return [{ insert: html, attrs: {} }];\n }\n\n // Parse HTML using DOM\n if (typeof document === 'undefined') {\n // SSR fallback: return raw HTML as single op\n return [{ insert: html, attrs: { _raw: true } }];\n }\n\n const doc = new DOMParser().parseFromString(`<div>${html}</div>`, 'text/html');\n const container = doc.body.firstChild;\n const ops = [];\n\n _walkNodes(container, {}, ops);\n\n // Ensure we end with a newline\n if (ops.length === 0 || !ops[ops.length - 1].insert.endsWith('\\n')) {\n ops.push({ insert: '\\n', attrs: {} });\n }\n\n return ops;\n}\n\nfunction _walkNodes(node, parentAttrs, ops) {\n for (const child of node.childNodes) {\n if (child.nodeType === 3) { // TEXT_NODE\n const text = child.textContent;\n if (text) {\n ops.push({ insert: text, attrs: { ...parentAttrs } });\n }\n } else if (child.nodeType === 1) { // ELEMENT_NODE\n const tag = child.tagName.toLowerCase();\n const attrs = { ...parentAttrs };\n\n // Track inline formatting\n if (tag === 'strong' || tag === 'b') attrs.bold = true;\n if (tag === 'em' || tag === 'i') attrs.italic = true;\n if (tag === 'u') attrs.underline = true;\n if (tag === 's' || tag === 'del' || tag === 'strike') attrs.strike = true;\n if (tag === 'code') attrs.code = true;\n if (tag === 'sub') attrs.sub = true;\n if (tag === 'sup') attrs.sup = true;\n if (tag === 'mark') attrs.highlight = true;\n\n // Links\n if (tag === 'a') {\n attrs.link = child.getAttribute('href') || '';\n if (child.getAttribute('target')) attrs.target = child.getAttribute('target');\n }\n\n // Images (inline)\n if (tag === 'img') {\n ops.push({\n insert: { type: 'image', src: child.getAttribute('src') || '' },\n attrs: {\n alt: child.getAttribute('alt') || '',\n width: child.getAttribute('width') || '',\n },\n });\n continue;\n }\n\n // Line breaks\n if (tag === 'br') {\n ops.push({ insert: '\\n', attrs: {} });\n continue;\n }\n\n // Block-level elements add newlines\n const isBlock = /^(p|div|h[1-6]|li|blockquote|pre|tr|figure|figcaption)$/.test(tag);\n\n _walkNodes(child, attrs, ops);\n\n if (isBlock) {\n ops.push({ insert: '\\n', attrs: {} });\n }\n }\n }\n}\n\nfunction _opsToHTML(ops, blockType) {\n if (!Array.isArray(ops) || ops.length === 0) return '';\n\n // For code/html blocks, return plain text\n if (blockType === 'code' || blockType === 'html') {\n return ops.map(op => typeof op.insert === 'string' ? op.insert : '').join('');\n }\n\n let html = '';\n for (const op of ops) {\n if (typeof op.insert === 'object' && op.insert !== null) {\n // Embedded object (e.g. image)\n if (op.insert.type === 'image') {\n html += `<img src=\"${_escAttr(op.insert.src)}\" alt=\"${_escAttr(op.attrs?.alt || '')}\">`;\n }\n continue;\n }\n\n if (typeof op.insert !== 'string') continue;\n\n let text = op.insert;\n // Don't convert trailing newlines to <br>\n if (text === '\\n') continue;\n\n // Escape HTML entities in text\n text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n\n // Replace internal newlines with <br>\n text = text.replace(/\\n/g, '<br>');\n\n // Apply formatting\n const a = op.attrs || {};\n if (a.code) text = `<code>${text}</code>`;\n if (a.bold) text = `<strong>${text}</strong>`;\n if (a.italic) text = `<em>${text}</em>`;\n if (a.underline) text = `<u>${text}</u>`;\n if (a.strike) text = `<s>${text}</s>`;\n if (a.sub) text = `<sub>${text}</sub>`;\n if (a.sup) text = `<sup>${text}</sup>`;\n if (a.highlight) text = `<mark>${text}</mark>`;\n if (a.link) text = `<a href=\"${_escAttr(a.link)}\"${a.target ? ` target=\"${_escAttr(a.target)}\"` : ''}>${text}</a>`;\n\n html += text;\n }\n\n return html;\n}\n\nfunction _escAttr(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n","import { EventEmitter } from './utils/EventEmitter.js';\nimport { el, placeCaretAtEnd, placeCaretAtStart, getCaretRect } from './utils/dom.js';\nimport { icons } from './utils/icons.js';\nimport { BlockManager } from './core/BlockManager.js';\nimport { MediaUploader } from './core/MediaUploader.js';\nimport { DragDrop } from './core/DragDrop.js';\nimport { BlockRenderer } from './blocks/BlockRenderer.js';\nimport { Header } from './ui/Header.js';\nimport { Toolbar } from './ui/Toolbar.js';\nimport { InserterPanel } from './ui/InserterPanel.js';\nimport { SettingsPanel } from './ui/SettingsPanel.js';\nimport { SlashMenu } from './ui/SlashMenu.js';\nimport { StatusBar } from './ui/StatusBar.js';\nimport { PluginRegistry } from './core/PluginRegistry.js';\nimport { Differ } from './core/Differ.js';\nimport { CollaborativeManager } from './core/CollaborativeManager.js';\nimport { createSanitizer } from './utils/sanitize.js';\nimport { normalizeHTML } from './utils/HtmlNormalizer.js';\nimport { blocksToDelta, deltaToBlocks } from './formats/DeltaFormat.js';\nimport { BLOCK_TYPES, CATEGORIES } from './blocks/registry.js';\n\n/**\n * NBDEditor — Gutenberg-style block editor.\n *\n * Usage:\n * const editor = new NBDEditor('#app', { ... });\n */\nexport class NBDEditor extends EventEmitter {\n constructor(selector, options = {}) {\n super();\n\n this.options = {\n siteName: 'My Site',\n authorName: 'Admin',\n showStatusBar: true,\n showSettingsPanel: false,\n showHeaderActions: false,\n placeholder: 'Start writing...',\n autoSaveInterval: 30000,\n uploadHandler: null, // async (file) => { url, id }\n maxFileSize: 10 * 1024 * 1024,\n onChooseMediaSource: null, // async/sync (type: 'video'|'audio') => 'url' | 'upload'\n content: null, // initial HTML content\n onChange: null,\n onSave: null,\n onPublish: null,\n sanitize: true, // Enable HTML sanitization\n sanitizeConfig: null, // Custom DOMPurify config\n ...options,\n };\n\n // Root element\n this.rootEl = typeof selector === 'string' ? document.querySelector(selector) : selector;\n if (!this.rootEl) throw new Error(`NBDEditor: element \"${selector}\" not found.`);\n\n // Plugin registry\n this.pluginRegistry = new PluginRegistry();\n\n // Register built-in block types\n for (const cat of CATEGORIES) {\n this.pluginRegistry.registerCategory(cat.id, cat.label);\n }\n for (const [type, def] of Object.entries(BLOCK_TYPES)) {\n this.pluginRegistry.registerBlockType(type, def);\n }\n\n // Sanitizer\n this._sanitize = this.options.sanitize\n ? createSanitizer(this.options.sanitizeConfig || {})\n : (html) => html;\n\n // Differ (change tracking)\n this.differ = new Differ();\n\n // Core modules\n this.blockManager = new BlockManager();\n this.mediaUploader = new MediaUploader({\n uploadHandler: this.options.uploadHandler,\n maxFileSize: this.options.maxFileSize,\n });\n\n // UI modules\n this.blockRenderer = new BlockRenderer(this);\n this.header = new Header(this);\n this.toolbar = new Toolbar(this);\n this.inserterPanel = new InserterPanel(this);\n this.settingsPanel = new SettingsPanel(this);\n this.slashMenu = new SlashMenu(this);\n this.statusBar = new StatusBar(this);\n\n // Collaborative manager (initialized on connect)\n this._collaborative = null;\n\n // State\n this._selectedBlockId = null;\n this._titleEl = null;\n this._blocksContainer = null;\n this._autoSaveTimer = null;\n this.el = null;\n this._htmlEditorModal = null;\n this._htmlEditorTextarea = null;\n this._htmlEditorTitle = null;\n this._htmlEditorBlockId = null;\n\n // Bound handlers for cleanup\n this._boundGlobalKeydown = (e) => this._handleGlobalKeydown(e);\n\n this._init();\n\n // Initialize plugins after editor is ready\n this.pluginRegistry.initPlugins(this);\n }\n\n /* ===== Initialization ===== */\n\n _init() {\n this.rootEl.innerHTML = '';\n this.rootEl.className = 'fe-root';\n\n // Header\n this.rootEl.appendChild(this.header.create());\n\n // Inserter panel\n this.rootEl.appendChild(this.inserterPanel.create());\n\n // Main wrapper\n this.el = el('div', { className: 'fe-editor-main' });\n\n // Canvas\n const canvas = el('div', { className: 'fe-editor-canvas', id: 'fe-canvas' });\n const content = el('div', { className: 'fe-editor-content' });\n\n // Blocks container — with ARIA attributes for accessibility\n this._blocksContainer = el('div', {\n className: 'fe-blocks-container',\n role: 'region',\n 'aria-label': 'Editor content',\n });\n content.appendChild(this._blocksContainer);\n\n canvas.appendChild(content);\n this.el.appendChild(canvas);\n\n // Settings panel\n if (this.options.showSettingsPanel) {\n this.el.appendChild(this.settingsPanel.create());\n }\n\n this.rootEl.appendChild(this.el);\n\n // Slash menu (appended to editor main for positioning)\n this.el.appendChild(this.slashMenu.create());\n\n // Status bar\n if (this.options.showStatusBar) {\n this.rootEl.appendChild(this.statusBar.create());\n }\n\n // Toast element with ARIA live region for screen readers\n this._toast = el('div', { className: 'fe-toast', role: 'status', 'aria-live': 'polite' });\n this.rootEl.appendChild(this._toast);\n\n // ARIA live region for non-visual notifications\n this._ariaLive = el('div', {\n className: 'fe-sr-only',\n role: 'log',\n 'aria-live': 'polite',\n 'aria-relevant': 'additions',\n style: { position: 'absolute', width: '1px', height: '1px', overflow: 'hidden', clip: 'rect(0,0,0,0)' },\n });\n this.rootEl.appendChild(this._ariaLive);\n this._createHtmlEditorModal();\n\n // Load initial content or create first block\n if (typeof this.options.content === 'string') {\n this.blockManager.fromJSON([{\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content: this.options.content,\n attrs: {},\n }]);\n } else if (this.options.content) {\n this.blockManager.fromJSON(this.options.content);\n } else {\n this.blockManager.addBlock('paragraph');\n }\n this._ensureAtLeastOneBlock();\n\n // Initialize differ baseline for change tracking\n this.differ.setBaseline(this.blockManager.toJSON());\n\n this.render();\n\n // Open settings panel by default\n if (this.options.showSettingsPanel) {\n this.settingsPanel.open();\n this._updateCanvasMargin();\n }\n\n // Keyboard shortcuts\n document.addEventListener('keydown', this._boundGlobalKeydown);\n\n // Auto-save\n if (this.options.autoSaveInterval > 0) {\n this._autoSaveTimer = setInterval(() => {\n this._syncAllBlockContent();\n this.statusBar.setSaved('Auto-saved: ' + new Date().toLocaleTimeString());\n this.emit('autosave', this.getData());\n }, this.options.autoSaveInterval);\n }\n\n // Listen for structural block changes (add, remove, move, type-change)\n this.blockManager.on('change', () => {\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n });\n\n // Drag & drop files onto the editor\n this._blocksContainer.addEventListener('dragover', (e) => e.preventDefault());\n this._blocksContainer.addEventListener('drop', async (e) => {\n if (e.dataTransfer.files.length > 0) {\n e.preventDefault();\n const results = await this.mediaUploader.handleDrop(e.dataTransfer);\n if (results) {\n const target =\n (this._selectedBlockId && this.blockManager.getBlock(this._selectedBlockId)) ||\n this.blockManager.blocks[0] ||\n this.blockManager.addBlock('paragraph');\n if (!target) return;\n const chunks = [];\n for (const res of results) {\n if (res.error) continue;\n const type = this.mediaUploader.getMediaType(res.file);\n const src = res.remoteUrl || res.localUrl;\n if (!src) continue;\n if (type === 'image') chunks.push(`<img src=\"${src}\" alt=\"\">`);\n else if (type === 'video') chunks.push(`<video controls src=\"${src}\"></video>`);\n else if (type === 'audio') chunks.push(`<audio controls src=\"${src}\"></audio>`);\n else if (type === 'file') chunks.push(`<a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${res.file.name || 'Download file'}</a>`);\n }\n const toAppend = chunks.join('\\n');\n if (toAppend) target.content = `${target.content || ''}${target.content ? '\\n' : ''}${toAppend}`;\n this.render();\n this.focusBlock(target.id);\n }\n }\n });\n\n // Click outside any block → deselect\n content.addEventListener('click', (e) => {\n if (!e.target.closest('.fe-block-wrapper') && !e.target.closest('.fe-block-appender') && !e.target.closest('.fe-block-toolbar')) {\n if (this._selectedBlockId) {\n this._selectedBlockId = null;\n this.render();\n }\n }\n });\n }\n\n /* ===== Rendering ===== */\n\n render() {\n this._ensureAtLeastOneBlock();\n this._blocksContainer.innerHTML = '';\n\n this.blockManager.blocks.forEach((block) => {\n const wrapper = el('section', {\n className: `fe-block-wrapper ${this._selectedBlockId === block.id ? 'fe-selected' : ''}`,\n dataset: { blockId: block.id },\n });\n\n // Toolbar (per-block, shown on selection)\n const tbContainer = el('div', { className: 'fe-block-toolbar-container' });\n if (this._selectedBlockId === block.id) {\n const tb = this.toolbar.create();\n this.toolbar.show(block.id);\n tb.scrollLeft = 0;\n tbContainer.appendChild(tb);\n requestAnimationFrame(() => this._positionBlockToolbar(tb, wrapper));\n }\n wrapper.appendChild(tbContainer);\n\n // Block content\n const rendered = this.blockRenderer.render(block);\n wrapper.appendChild(rendered);\n\n // Click to select\n wrapper.addEventListener('click', (e) => {\n const clickedContent = e.target.closest('.fe-block-content');\n const clickedEditable = e.target.closest('[contenteditable]');\n const clickedCell = e.target.closest('td,th');\n let clickedEditableIndex = -1;\n if (clickedEditable && wrapper.contains(clickedEditable)) {\n const editables = Array.from(wrapper.querySelectorAll('[contenteditable]'));\n clickedEditableIndex = editables.indexOf(clickedEditable);\n }\n let clickedCellPos = null;\n if (clickedCell) {\n const row = clickedCell.closest('tr');\n const table = clickedCell.closest('table');\n if (row && table) {\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n const cols = Array.from(row.querySelectorAll('th,td'));\n const colIndex = cols.indexOf(clickedCell);\n if (rowIndex >= 0 && colIndex >= 0) clickedCellPos = { rowIndex, colIndex };\n }\n }\n if (!e.target.closest('.fe-block-toolbar') && !e.target.closest('.fe-link-popover')) {\n if (this._selectedBlockId === block.id && (clickedContent || clickedEditable || clickedCell)) {\n return;\n }\n const blockId = block.id;\n this.selectBlock(blockId);\n // selectBlock calls render() which destroys DOM; focus the NEW contenteditable\n // Use double-rAF to ensure DOM is fully painted before focusing\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n const contentEl = this._getBlockContentEl(blockId);\n if (contentEl) {\n if (clickedCellPos) {\n const rows = Array.from(contentEl.querySelectorAll('tr'));\n const row = rows[clickedCellPos.rowIndex];\n const cols = row ? Array.from(row.querySelectorAll('th,td')) : [];\n const nextCell = cols[clickedCellPos.colIndex] || cols[cols.length - 1] || null;\n if (nextCell) {\n nextCell.focus();\n const range = document.createRange();\n range.selectNodeContents(nextCell);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n }\n if (clickedEditableIndex >= 0) {\n const newWrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n const editables = newWrapper ? Array.from(newWrapper.querySelectorAll('[contenteditable]')) : [];\n const targetEditable = editables[clickedEditableIndex] || editables[0] || null;\n if (targetEditable) {\n targetEditable.focus();\n placeCaretAtEnd(targetEditable);\n return;\n }\n }\n placeCaretAtEnd(contentEl);\n }\n });\n });\n }\n });\n\n // Drag handle setup\n const dragHandle = wrapper.querySelector('.fe-tb-drag');\n if (dragHandle) {\n const dd = new DragDrop(this._blocksContainer);\n dd.initDrag(dragHandle, wrapper, block.id);\n dd.on('drop', ({ fromId, toId, position }) => {\n const fromIdx = this.blockManager.getIndex(fromId);\n let toIdx = this.blockManager.getIndex(toId);\n if (position === 'after') toIdx++;\n if (fromIdx < toIdx) toIdx--;\n const [moved] = this.blockManager.blocks.splice(fromIdx, 1);\n this.blockManager.blocks.splice(toIdx, 0, moved);\n this.blockManager.saveSnapshot();\n this.render();\n });\n }\n\n this._blocksContainer.appendChild(wrapper);\n });\n\n // Single global appender (outside blocks) to match WP-like flow.\n const appender = el('button', {\n type: 'button',\n className: 'fe-block-appender',\n 'aria-label': 'Add block',\n });\n const plusIcon = el('span', { className: 'fe-plus-icon', innerHTML: icons.plus });\n const label = el('span', {}, ['Add block']);\n appender.appendChild(plusIcon);\n appender.appendChild(label);\n appender.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const targetId = this._selectedBlockId || this.blockManager.blocks[this.blockManager.blocks.length - 1]?.id;\n if (targetId) this.selectBlock(targetId);\n this.inserterPanel.open(appender, { forceNewBlock: true });\n });\n this._blocksContainer.appendChild(appender);\n\n this.statusBar.update();\n }\n\n /* ===== Block Operations ===== */\n\n selectBlock(id) {\n if (this._selectedBlockId === id) {\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n return;\n }\n this._selectedBlockId = id;\n this.render();\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n this.emit('block:select', id);\n }\n\n focusBlock(id) {\n this.selectBlock(id);\n setTimeout(() => {\n const contentEl = this._getBlockContentEl(id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtEnd(contentEl);\n }\n }, 0);\n }\n\n insertBlockAtSelection(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const selectedId = this._selectedBlockId;\n const block = this.blockManager.addBlock(type, data, selectedId || null);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n insertBlockAtEnd(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const block = this.blockManager.addBlock(type, data);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n /* ===== Block Input Handling ===== */\n\n _onBlockInput(block, node) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (node.textContent || '')\n : node.innerHTML;\n this.statusBar.update();\n\n // Slash command detection\n const text = node.textContent;\n if (text === '/') {\n const rect = getCaretRect() || node.getBoundingClientRect();\n this.slashMenu.open(block, rect);\n } else if (text.startsWith('/') && text.length > 1) {\n if (this.slashMenu.isOpen()) {\n this.slashMenu.filter(text.slice(1).toLowerCase());\n }\n } else {\n if (this.slashMenu.isOpen()) this.slashMenu.close();\n }\n\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n this.emit('input', block);\n }\n\n _onBlockKeydown(e, block, node) {\n // Slash menu takes priority\n if (this.slashMenu.isOpen() && this.slashMenu.handleKeydown(e)) return;\n // Keep Enter behavior inside the same block.\n // New blocks are created explicitly via inserter/add controls.\n\n // Tab in list blocks: indent / outdent list items\n if (e.key === 'Tab' && (block.type === 'list' || block.type === 'ordered-list')) {\n e.preventDefault();\n document.execCommand(e.shiftKey ? 'outdent' : 'indent', false, null);\n this._syncCurrentBlockContent();\n return;\n }\n\n // Table navigation + row creation with Tab\n if (e.key === 'Tab') {\n const cell = this._getSelectionTableCell();\n if (cell) {\n e.preventDefault();\n this._handleTableTab(cell, e.shiftKey);\n this._syncCurrentBlockContent();\n return;\n }\n }\n\n // Arrow Up at start: focus previous block\n if (e.key === 'ArrowUp') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.top <= nodeRect.top + 2) {\n const prev = this.blockManager.getPrevBlock(block.id);\n if (prev) {\n e.preventDefault();\n this.focusBlock(prev.id);\n }\n }\n }\n }\n\n // Arrow Down at end: focus next block\n if (e.key === 'ArrowDown') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.bottom >= nodeRect.bottom - 2) {\n const next = this.blockManager.getNextBlock(block.id);\n if (next) {\n e.preventDefault();\n const contentEl = this._getBlockContentEl(next.id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtStart(contentEl);\n this.selectBlock(next.id);\n }\n }\n }\n }\n }\n\n // Tab in code block\n if (e.key === 'Tab' && (block.type === 'code' || block.type === 'html')) {\n e.preventDefault();\n document.execCommand('insertText', false, ' ');\n }\n }\n\n /* ===== Helpers ===== */\n\n _getBlockContentEl(blockId) {\n const wrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n return wrapper?.querySelector('.fe-block-content') || wrapper?.querySelector('[contenteditable]');\n }\n\n _getSelectedBlockEl() {\n if (!this._selectedBlockId) return null;\n return this._blocksContainer.querySelector(`[data-block-id=\"${this._selectedBlockId}\"]`);\n }\n\n _syncCurrentBlockContent() {\n if (!this._selectedBlockId) return;\n const block = this.blockManager.getBlock(this._selectedBlockId);\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (block && contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n }\n\n _syncAllBlockContent() {\n this.blockManager.blocks.forEach((block) => {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n });\n }\n\n _generateSlug() {\n const slug = (this._titleEl?.value || '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n const slugEl = document.getElementById('fe-url-slug');\n if (slugEl) slugEl.value = slug;\n }\n\n _updateCanvasMargin() {\n if (!this.options.showSettingsPanel) return;\n const canvas = this.el.querySelector('.fe-editor-canvas');\n if (canvas) {\n canvas.classList.toggle('fe-panel-open', this.settingsPanel.isOpen());\n }\n }\n\n _createHtmlEditorModal() {\n const overlay = el('div', { className: 'fe-html-modal-overlay' });\n const modal = el('div', { className: 'fe-html-modal' });\n const header = el('div', { className: 'fe-html-modal-header' });\n const title = el('h3', { className: 'fe-html-modal-title' }, ['Edit as HTML']);\n const closeBtn = el('button', {\n type: 'button',\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this._closeBlockHtmlEditor(),\n });\n header.appendChild(title);\n header.appendChild(closeBtn);\n\n const textarea = el('textarea', {\n className: 'fe-html-modal-textarea',\n spellcheck: 'false',\n placeholder: 'Edit block HTML...',\n });\n\n const actions = el('div', { className: 'fe-html-modal-actions' });\n const cancelBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Cancel',\n onClick: () => this._closeBlockHtmlEditor(),\n });\n const applyBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Apply HTML',\n onClick: () => this._applyBlockHtmlEditor(),\n });\n actions.appendChild(cancelBtn);\n actions.appendChild(applyBtn);\n\n modal.appendChild(header);\n modal.appendChild(textarea);\n modal.appendChild(actions);\n overlay.appendChild(modal);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeBlockHtmlEditor();\n });\n textarea.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this._closeBlockHtmlEditor();\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') this._applyBlockHtmlEditor();\n });\n\n this.rootEl.appendChild(overlay);\n this._htmlEditorModal = overlay;\n this._htmlEditorTextarea = textarea;\n this._htmlEditorTitle = title;\n }\n\n _parseBlockFromHTML(html, fallbackType = 'paragraph') {\n const raw = (html || '').trim();\n if (!raw) return { type: fallbackType, content: '', attrs: {} };\n if (typeof document === 'undefined') return { type: 'html', content: raw, attrs: {} };\n\n const wrap = document.createElement('div');\n wrap.innerHTML = raw;\n const first = wrap.firstElementChild;\n const onlyOneElement =\n wrap.childElementCount === 1 &&\n Array.from(wrap.childNodes).every((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent.trim() === '');\n\n if (!first || !onlyOneElement) {\n return { type: 'html', content: raw, attrs: {} };\n }\n\n const tag = first.tagName.toLowerCase();\n if (tag === 'p') return { type: 'paragraph', content: first.innerHTML, attrs: {} };\n if (tag === 'h2') return { type: 'heading', content: first.innerHTML, attrs: {} };\n if (tag === 'h3') return { type: 'heading-3', content: first.innerHTML, attrs: {} };\n if (tag === 'h4') return { type: 'heading-4', content: first.innerHTML, attrs: {} };\n if (tag === 'blockquote') return { type: 'quote', content: first.innerHTML, attrs: {} };\n if (tag === 'ul') return { type: 'list', content: first.innerHTML, attrs: {} };\n if (tag === 'ol') return { type: 'ordered-list', content: first.innerHTML, attrs: {} };\n if (tag === 'hr') return { type: 'separator', content: '', attrs: {} };\n if (tag === 'img') {\n const styleWidth = _readPercentWidth(first.getAttribute('style') || '');\n return {\n type: 'image',\n content: first.getAttribute('src') || '',\n attrs: {\n alt: first.getAttribute('alt') || '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n if (tag === 'figure') {\n const img = first.querySelector('img');\n if (img) {\n const caption = first.querySelector('figcaption');\n const styleWidth = _readPercentWidth(img.getAttribute('style') || '');\n return {\n type: 'image',\n content: img.getAttribute('src') || '',\n attrs: {\n alt: img.getAttribute('alt') || '',\n caption: caption ? caption.innerHTML : '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n }\n if (tag === 'pre') {\n const code = first.querySelector('code');\n return {\n type: 'code',\n content: code ? (code.textContent || '') : (first.textContent || ''),\n attrs: {},\n };\n }\n\n return { type: 'html', content: raw, attrs: {} };\n }\n\n /* ===== Global Keyboard Shortcuts ===== */\n\n _handleGlobalKeydown(e) {\n const mod = e.ctrlKey || e.metaKey;\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.rootEl.contains(window.getSelection().anchorNode));\n\n if (mod && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n this.undo({ preferNative: inEditable });\n }\n if (mod && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\n e.preventDefault();\n this.redo({ preferNative: inEditable });\n }\n if (mod && e.key === 's') {\n e.preventDefault();\n this.save();\n }\n if (mod && e.key === 'b') {\n e.preventDefault();\n document.execCommand('bold', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'i') {\n e.preventDefault();\n document.execCommand('italic', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'u') {\n e.preventDefault();\n document.execCommand('underline', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'k') {\n e.preventDefault();\n this.toolbar._showLinkPopover();\n }\n if (mod && e.key === 'a') {\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (contentEl && this.rootEl.contains(document.activeElement)) {\n e.preventDefault();\n const range = document.createRange();\n range.selectNodeContents(contentEl);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n }\n\n /* ===== Public API ===== */\n\n /** Get all editor data as a JSON object. */\n getData() {\n this._syncAllBlockContent();\n const mergedHtml = this.blockManager.toHTML();\n return { content: mergedHtml };\n }\n\n /** Set editor content from a content string or { content } object. */\n setData(data) {\n let content = typeof data === 'string'\n ? data\n : (typeof data?.content === 'string' ? data.content : '');\n\n // Sanitize incoming content\n content = this._sanitize(content);\n\n this.blockManager.fromJSON([\n {\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content,\n attrs: {},\n },\n ]);\n this.differ.setBaseline(this.blockManager.toJSON());\n this.render();\n }\n\n /** Export blocks as HTML string. */\n toHTML() {\n this._syncAllBlockContent();\n return this.blockManager.toHTML();\n }\n\n toggleBlockHtmlMode(blockId = this._selectedBlockId) {\n if (!blockId) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n if (block.type === 'html') {\n const fallbackType = block.attrs?.__sourceType || 'paragraph';\n const parsed = this._parseBlockFromHTML(block.content || '', fallbackType);\n block.type = parsed.type === 'html' ? fallbackType : parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this.render();\n this.focusBlock(blockId);\n return;\n }\n\n const html = this.blockManager.blockToHTML(block);\n block.attrs = { ...(block.attrs || {}), __sourceType: block.type };\n block.type = 'html';\n block.content = html;\n this.render();\n this.focusBlock(blockId);\n }\n\n openBlockHtmlEditor(blockId = this._selectedBlockId) {\n if (!blockId || !this._htmlEditorModal || !this._htmlEditorTextarea) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n this._htmlEditorBlockId = blockId;\n this._htmlEditorTitle.textContent = `Edit as HTML: ${block.type}`;\n this._htmlEditorTextarea.value = this.blockManager.blockToHTML(block);\n this._htmlEditorModal.classList.add('fe-open');\n setTimeout(() => {\n this._htmlEditorTextarea.focus();\n this._htmlEditorTextarea.select();\n }, 0);\n }\n\n _closeBlockHtmlEditor() {\n if (!this._htmlEditorModal) return;\n this._htmlEditorModal.classList.remove('fe-open');\n this._htmlEditorBlockId = null;\n }\n\n _applyBlockHtmlEditor() {\n if (!this._htmlEditorBlockId || !this._htmlEditorTextarea) return;\n const block = this.blockManager.getBlock(this._htmlEditorBlockId);\n if (!block) return this._closeBlockHtmlEditor();\n\n const parsed = this._parseBlockFromHTML(this._htmlEditorTextarea.value, block.type);\n block.type = parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this._closeBlockHtmlEditor();\n this.render();\n this.focusBlock(block.id);\n }\n\n /** Save draft (emits save event). */\n save() {\n const data = this.getData();\n this.header.setStatus('Draft saved');\n this.statusBar.setSaved('Last saved: ' + new Date().toLocaleTimeString());\n this._showToast('Draft saved');\n if (this.options.onSave) this.options.onSave(data);\n this.emit('save', data);\n }\n\n /** Publish (emits publish event). */\n publish() {\n const data = this.getData();\n this.header.setStatus('Published', '#00a32a');\n this._showToast('Post published!');\n if (this.options.onPublish) this.options.onPublish(data);\n this.emit('publish', data);\n }\n\n /** Get / set the title. */\n getTitle() { return this._titleEl?.value || ''; }\n setTitle(title) { if (this._titleEl) this._titleEl.value = title; }\n\n undo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('undo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockUndo = this.blockManager.undo();\n if (didBlockUndo) this.render();\n return didBlockUndo;\n }\n\n redo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('redo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockRedo = this.blockManager.redo();\n if (didBlockRedo) this.render();\n return didBlockRedo;\n }\n\n /* ===== Plugin System ===== */\n\n /** Register a custom block type at runtime. */\n registerBlockType(type, definition) {\n this.pluginRegistry.registerBlockType(type, definition);\n }\n\n /** Register a plugin (bundles block types + lifecycle hooks). */\n registerPlugin(plugin) {\n const registered = this.pluginRegistry.registerPlugin(plugin);\n // Initialize the plugin immediately if editor is already set up\n if (registered && typeof registered.init === 'function') {\n try { registered.init(this); } catch (e) { console.error(e); }\n }\n return registered;\n }\n\n /* ===== Delta Format ===== */\n\n /** Export blocks as Delta format (structured ops). */\n getDelta() {\n this._syncAllBlockContent();\n return blocksToDelta(this.blockManager.toJSON());\n }\n\n /** Import content from Delta format. */\n setDelta(delta) {\n const blocks = deltaToBlocks(delta);\n this.blockManager.fromJSON(blocks);\n this.render();\n }\n\n /* ===== HTML Normalization ===== */\n\n /** Normalize an HTML string for consistent round-tripping. */\n normalizeHTML(html) {\n return normalizeHTML(html);\n }\n\n /* ===== Sanitization ===== */\n\n /** Sanitize HTML content (strips XSS vectors). */\n sanitizeHTML(html) {\n return this._sanitize(html);\n }\n\n /* ===== Diff / Patch ===== */\n\n /** Get accumulated block-level changes since last call. */\n getChanges() {\n this._syncAllBlockContent();\n this.differ.diff(this.blockManager.toJSON());\n return this.differ.getChanges();\n }\n\n /* ===== Collaborative Editing ===== */\n\n /**\n * Connect to a collaborative editing server.\n * @param {string} wsUrl - WebSocket URL.\n * @param {Object} [options] - Connection options.\n * @returns {CollaborativeManager}\n */\n connectCollaborative(wsUrl, options = {}) {\n if (this._collaborative) {\n this._collaborative.disconnect();\n }\n this._collaborative = new CollaborativeManager(this, wsUrl, options);\n this._collaborative.connect();\n return this._collaborative;\n }\n\n /** Disconnect from collaborative server. */\n disconnectCollaborative() {\n if (this._collaborative) {\n this._collaborative.disconnect();\n this._collaborative = null;\n }\n }\n\n /** Destroy editor instance. */\n destroy() {\n if (this._autoSaveTimer) clearInterval(this._autoSaveTimer);\n if (this._collaborative) this._collaborative.disconnect();\n this.pluginRegistry.destroyAll();\n document.removeEventListener('keydown', this._boundGlobalKeydown);\n this.slashMenu.destroy();\n this.toolbar.hide();\n this.rootEl.innerHTML = '';\n this._listeners = {};\n }\n\n _showToast(msg) {\n this._toast.textContent = msg;\n this._toast.classList.add('fe-show');\n setTimeout(() => this._toast.classList.remove('fe-show'), 2500);\n // Also announce to screen readers\n this._announce(msg);\n }\n\n /** Announce a message to screen readers via ARIA live region. */\n _announce(msg) {\n if (this._ariaLive) {\n const node = document.createElement('span');\n node.textContent = msg;\n this._ariaLive.appendChild(node);\n // Clean up old announcements to prevent DOM bloat\n if (this._ariaLive.childNodes.length > 5) {\n this._ariaLive.removeChild(this._ariaLive.firstChild);\n }\n }\n }\n\n _positionBlockToolbar(toolbarEl, wrapperEl) {\n if (!toolbarEl || !wrapperEl) return;\n const viewportPadding = 8;\n\n toolbarEl.classList.remove('fe-toolbar-below');\n toolbarEl.style.top = '-44px';\n toolbarEl.style.left = '0px';\n\n const toolbarRect = toolbarEl.getBoundingClientRect();\n const wrapperRect = wrapperEl.getBoundingClientRect();\n\n let shiftX = 0;\n if (toolbarRect.right > window.innerWidth - viewportPadding) {\n shiftX -= toolbarRect.right - (window.innerWidth - viewportPadding);\n }\n if (toolbarRect.left + shiftX < viewportPadding) {\n shiftX += viewportPadding - (toolbarRect.left + shiftX);\n }\n toolbarEl.style.left = `${Math.round(shiftX)}px`;\n\n const topIfAbove = wrapperRect.top - toolbarRect.height - 6;\n const shouldPlaceBelow = topIfAbove < viewportPadding;\n if (shouldPlaceBelow) {\n toolbarEl.classList.add('fe-toolbar-below');\n toolbarEl.style.top = '6px';\n }\n wrapperEl.classList.toggle('fe-toolbar-inset', shouldPlaceBelow);\n }\n\n _getSelectionTableCell() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n let node = sel.anchorNode;\n if (!node) return null;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return null;\n const cell = node.closest('td,th');\n if (!cell) return null;\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (!contentEl || !contentEl.contains(cell)) return null;\n return cell;\n }\n\n _handleTableTab(currentCell, reverse = false) {\n const row = currentCell.closest('tr');\n const table = currentCell.closest('table');\n if (!row || !table) return;\n\n const rowCells = Array.from(row.querySelectorAll('th,td'));\n const cellIndex = rowCells.indexOf(currentCell);\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n\n if (reverse) {\n if (cellIndex > 0) {\n this._placeCaretInCell(rowCells[cellIndex - 1]);\n return;\n }\n if (rowIndex > 0) {\n const prevRowCells = Array.from(rows[rowIndex - 1].querySelectorAll('th,td'));\n this._placeCaretInCell(prevRowCells[prevRowCells.length - 1]);\n }\n return;\n }\n\n if (cellIndex < rowCells.length - 1) {\n this._placeCaretInCell(rowCells[cellIndex + 1]);\n return;\n }\n\n if (rowIndex < rows.length - 1) {\n const nextRowCells = Array.from(rows[rowIndex + 1].querySelectorAll('th,td'));\n this._placeCaretInCell(nextRowCells[0]);\n return;\n }\n\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n const tbody = table.querySelector('tbody');\n if (tbody) tbody.appendChild(newRow);\n else table.appendChild(newRow);\n this._placeCaretInCell(newRow.querySelector('td'));\n }\n\n _placeCaretInCell(cell) {\n if (!cell) return;\n if ((cell.innerHTML || '').trim() === '') cell.innerHTML = '<br>';\n const range = document.createRange();\n range.selectNodeContents(cell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n insertSingleBlockType(type, data = {}) {\n const block = this._getInsertionTargetBlock();\n if (!block) return false;\n\n const snippet = this._snippetForType(type, data);\n if (!snippet) return false;\n\n if (typeof document.execCommand === 'function') {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n contentEl.focus();\n const ok = document.execCommand('insertHTML', false, snippet);\n if (ok) {\n this._focusEditableTail(contentEl);\n this._syncCurrentBlockContent();\n return true;\n }\n }\n }\n\n block.content = `${block.content || ''}${block.content ? '\\n' : ''}${snippet}`;\n return true;\n }\n\n _snippetForType(type, data = {}) {\n if (type === 'separator') return '<hr><p><br></p>';\n if (type === 'spacer') return `<div style=\"height:${Number(data?.height) || 48}px\"></div><p><br></p>`;\n if (type === 'table') {\n return [\n '<table border=\"1\" style=\"width:100%;border-collapse:collapse;\">',\n '<tbody>',\n '<tr><td>Cell 1</td><td>Cell 2</td></tr>',\n '<tr><td>Cell 3</td><td>Cell 4</td></tr>',\n '</tbody>',\n '</table>',\n '<p><br></p>',\n ].join('');\n }\n if (type === 'columns') {\n return [\n '<div class=\"fe-inline-columns\">',\n '<div class=\"fe-inline-column\"><p>Column 1</p></div>',\n '<div class=\"fe-inline-column\"><p>Column 2</p></div>',\n '</div>',\n '<p><br></p>',\n ].join('');\n }\n\n if (type === 'button') {\n return '<p><a href=\"#\" style=\"display:inline-block;background:#2271b1;color:#fff;padding:10px 24px;border-radius:4px;text-decoration:none;\" contenteditable=\"false\">Button</a></p><p><br></p>';\n }\n if (type === 'video') {\n const src = String(data?.url || '').trim();\n return src\n ? `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`\n : '<video controls style=\"width:100%;max-width:100%;\"></video><p><br></p>';\n }\n if (type === 'audio') {\n const src = String(data?.url || '').trim();\n return src\n ? `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`\n : '<audio controls style=\"width:100%;\"></audio><p><br></p>';\n }\n if (type === 'file') {\n const url = String(data?.url || '').trim();\n const name = String(data?.name || 'Download file').trim();\n return url ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${name}</a></p><p><br></p>` : null;\n }\n if (type === 'embed') {\n const url = String(data?.url || '').trim();\n return url\n ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${url}</a></p><p><br></p>`\n : '<p>Paste embed URL here</p><p><br></p>';\n }\n return null;\n }\n\n _focusEditableTail(contentEl) {\n if (!contentEl) return;\n let tail = contentEl.lastElementChild;\n const needsTail = !tail || tail.tagName !== 'P';\n if (needsTail) {\n tail = document.createElement('p');\n tail.innerHTML = '<br>';\n contentEl.appendChild(tail);\n } else if ((tail.innerHTML || '').trim() === '') {\n tail.innerHTML = '<br>';\n }\n\n const range = document.createRange();\n range.selectNodeContents(tail);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n _ensureAtLeastOneBlock() {\n if (!Array.isArray(this.blockManager.blocks) || this.blockManager.blocks.length === 0) {\n return this.blockManager.addBlock('paragraph');\n }\n return this.blockManager.blocks[0];\n }\n\n _getInsertionTargetBlock() {\n const selected =\n this._selectedBlockId\n ? this.blockManager.getBlock(this._selectedBlockId)\n : null;\n if (selected) return selected;\n\n const last = this.blockManager.blocks[this.blockManager.blocks.length - 1];\n if (last) return last;\n\n return this.blockManager.addBlock('paragraph');\n }\n}\n\nfunction _readPercentWidth(style) {\n const match = /width\\s*:\\s*([0-9.]+)%/i.exec(style || '');\n if (!match) return null;\n const value = Number(match[1]);\n if (!Number.isFinite(value)) return null;\n return Math.max(10, Math.min(100, Math.round(value)));\n}\n","/**\n * React wrapper for NBDEditor.\n *\n * Supports both controlled and uncontrolled usage:\n *\n * Controlled (like React Quill):\n * const [content, setContent] = useState('<p>Hello</p>');\n * <ReactNBDEditor content={content} onChange={(d) => setContent(d.content)} />\n *\n * Uncontrolled (initial value + ref):\n * <ReactNBDEditor content=\"<p>Hello</p>\" ref={editorRef} />\n *\n * Guarded so the module can be safely imported in environments where React\n * is not available (e.g. vanilla-JS UMD usage). When React is missing,\n * `ReactNBDEditor` will be `null`.\n */\nimport * as React from 'react';\nimport { NBDEditor } from '../NBDEditor.js';\n\n// Guard: React may be undefined in vanilla-JS / UMD without React loaded.\nconst _hasReact = typeof React !== 'undefined' && React !== null && typeof React.forwardRef === 'function';\n\nfunction ReactNBDEditorComponent(props, ref) {\n const {\n className,\n style,\n content,\n onChange,\n onSave,\n onPublish,\n onReady,\n debounceMs,\n ...editorOptions\n } = props || {};\n\n const hostRef = React.useRef(null);\n const editorRef = React.useRef(null);\n const lastContentRef = React.useRef(undefined);\n\n // Use refs for callbacks so the editor always calls the latest version.\n // This fixes the stale closure issue where onChange/onSave/onPublish\n // captured at mount time would never update.\n const onChangeRef = React.useRef(onChange);\n const onSaveRef = React.useRef(onSave);\n const onPublishRef = React.useRef(onPublish);\n const debounceTimerRef = React.useRef(null);\n\n onChangeRef.current = onChange;\n onSaveRef.current = onSave;\n onPublishRef.current = onPublish;\n\n // ── Initialize editor (one-time) ──────────────────────────────────\n React.useEffect(() => {\n if (!hostRef.current) return undefined;\n\n const initialOptions = {\n ...editorOptions,\n // Wire up onChange through a ref so it always calls the latest prop\n onChange: (data) => {\n const nextContent = typeof data?.content === 'string' ? data.content : '';\n lastContentRef.current = nextContent;\n\n const notify = () => {\n if (typeof onChangeRef.current === 'function') onChangeRef.current(data);\n };\n\n // Optional debounce for controlled mode performance\n if (debounceMs && debounceMs > 0) {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = setTimeout(notify, debounceMs);\n } else {\n notify();\n }\n },\n onSave: (data) => {\n if (typeof onSaveRef.current === 'function') onSaveRef.current(data);\n },\n onPublish: (data) => {\n if (typeof onPublishRef.current === 'function') onPublishRef.current(data);\n },\n ...(typeof content === 'string' ? { content } : {}),\n };\n\n const editor = new NBDEditor(hostRef.current, initialOptions);\n editorRef.current = editor;\n lastContentRef.current = typeof content === 'string' ? content : undefined;\n if (typeof onReady === 'function') onReady(editor);\n\n return () => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n if (editorRef.current) {\n editorRef.current.destroy();\n editorRef.current = null;\n }\n };\n // Intentionally one-time init; options should be stable at mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ── Sync content prop → editor (controlled mode) ─────────────────\n React.useEffect(() => {\n if (!editorRef.current) return;\n if (typeof content !== 'string') return;\n\n // Skip if this content came from the editor's own onChange\n if (content === lastContentRef.current) return;\n\n // Normalize: compare trimmed versions to avoid whitespace mismatches\n const currentHTML = editorRef.current.toHTML();\n if (content.trim() === currentHTML.trim()) {\n lastContentRef.current = content;\n return;\n }\n\n // Actually different content from outside — update the editor\n editorRef.current.setData({ content });\n lastContentRef.current = content;\n }, [content]);\n\n // ── Imperative ref handle ─────────────────────────────────────────\n React.useImperativeHandle(ref, () => ({\n getInstance: () => editorRef.current,\n getData: () => editorRef.current?.getData(),\n setData: (data) => editorRef.current?.setData(data),\n toHTML: () => editorRef.current?.toHTML(),\n save: () => editorRef.current?.save(),\n publish: () => editorRef.current?.publish(),\n undo: (opts) => editorRef.current?.undo(opts),\n redo: (opts) => editorRef.current?.redo(opts),\n destroy: () => editorRef.current?.destroy(),\n }), []);\n\n return React.createElement('div', {\n ref: hostRef,\n className,\n style,\n });\n}\n\nexport const ReactNBDEditor = _hasReact ? React.forwardRef(ReactNBDEditorComponent) : null;\n"],"names":["EventEmitter","constructor","this","_listeners","on","event","fn","push","off","list","filter","f","emit","args","forEach","once","wrapper","el","tag","attrs","children","node","document","createElement","k","v","Object","entries","className","assign","style","dk","dv","dataset","startsWith","addEventListener","slice","toLowerCase","contentEditable","innerHTML","setAttribute","child","Array","isArray","appendChild","createTextNode","Node","generateId","Date","now","toString","Math","random","placeCaretAtEnd","element","focus","range","createRange","selectNodeContents","collapse","sel","window","getSelection","removeAllRanges","addRange","svg","inner","vb","icons","plus","undo","redo","settings","bold","italic","underline","strikethrough","link","code","alignLeft","alignCenter","alignRight","image","heading","paragraph","quote","orderedList","separator","table","button","columns","spacer","embed","gallery","video","audio","file","dragHandle","filled","arrowUp","arrowDown","trash","close","inlineCode","upload","html","pullquote","BlockManager","super","blocks","_undoStack","_redoStack","_maxHistory","JSON","stringify","addBlock","type","data","afterId","block","id","content","idx","findIndex","b","splice","_pushUndo","removeBlock","length","removed","updateBlock","patch","getBlock","changeBlockType","newType","moveBlock","direction","newIdx","duplicateBlock","clone","find","getIndex","getPrevBlock","getNextBlock","toJSON","map","fromJSON","toHTML","blockToHTML","join","toHTMLBlocks","c","test","_escText","width","Number","isFinite","max","min","round","_escAttr","alt","caption","height","rows","cols","r","ci","url","numCols","colsHTML","i","filename","next","shift","saveSnapshot","pop","parse","state","getWordCount","text","tmp","textContent","trim","split","w","getCharCount","replace","str","String","MediaUploader","options","uploadHandler","maxFileSize","allowedImageTypes","allowedVideoTypes","allowedAudioTypes","_fileInput","openFilePicker","accept","multiple","Promise","resolve","remove","input","display","body","files","click","processFile","size","err","name","toFixed","error","localUrl","_readAsDataURL","result","remoteUrl","message","processFiles","all","handlePaste","clipboardData","imageItems","items","item","getAsFile","Boolean","handleDrop","dataTransfer","getMediaType","reject","reader","FileReader","onload","onerror","readAsDataURL","DragDrop","container","_dragging","_placeholder","_offsetY","_bound","_enabled","enable","disable","initDrag","handleEl","wrapperEl","blockId","cursor","e","preventDefault","opacity","effectAllowed","setData","_removePlaceholder","dropEffect","rect","getBoundingClientRect","midY","top","position","clientY","_showPlaceholder","fromId","toId","referenceEl","cssText","parentNode","insertBefore","nextSibling","removeChild","BLOCK_TYPES","label","description","icon","category","hasContent","contentTag","placeholder","isMedia","CATEGORIES","getBlocksByCategory","catId","def","searchBlocks","query","q","includes","BlockRenderer","editor","render","_renderParagraph","_renderMediaBlock","_renderContentBlock","_renderSeparator","_renderSpacer","_renderColumns","_renderTable","isRawTextBlock","isEmpty","initialHTML","empty","_bindContentEvents","_renderImageBlock","_renderGalleryBlock","_renderVideoBlock","_renderAudioBlock","_renderFileBlock","_renderMediaPlaceholder","_normalizeImageWidth","fig","img","src","maxWidth","borderRadius","overlay","replaceBtn","onClick","_triggerImageUpload","removeBtn","resizeHandle","title","stopPropagation","selectBlock","startX","clientX","startWidth","parentWidth","onMove","ev","delta","nextPercent","onUp","removeEventListener","statusBar","update","sizeControls","pct","btn","images","grid","addMore","_triggerGalleryUpload","controls","infoDiv","filesize","downloadLink","href","download","iconEl","desc","btnRow","uploadBtn","_handleMediaUpload","urlInput","key","value","_setupDropZone","handle","startY","startH","newH","col","current","tr","cell","mediaUploader","results","res","bytes","classList","add","async","updateEmptyState","_selectedBlockId","activeElement","setTimeout","_onBlockInput","querySelector","_onBlockKeydown","getData","execCommand","then","numeric","Header","create","left","inserterBtn","inserterPanel","toggle","currentTarget","_iconBtn","activeEl","inEditable","isContentEditable","rootEl","contains","anchorNode","preferNative","center","right","showHeaderActions","draftBtn","save","publishBtn","publish","showSettingsPanel","childNodes","settingsPanel","_updateCanvasMargin","setStatus","color","iconHTML","Toolbar","_linkPopover","_fontSizeSelect","_onSelectionChange","_statefulButtons","_savedLinkRange","_tableToolsSep","_tableRowBtn","_tableColBtn","_createLinkPopover","show","blockManager","hide","getActiveBlockId","dragBtn","_addBtn","_initToolbarDrag","_addSep","textTypes","htmlEditableTypes","select","opt","o","selected","blockNow","ensureParagraphContext","contentEl","_getBlockContentEl","_syncCurrentBlockContent","focusBlock","fontSizeSelect","_applyFontSize","_syncFontSizeSelect","_bindFontSizeTracking","_addStatefulBtn","_exec","_wrapInlineCode","_showLinkPopover","_addTextBtn","_addTableRow","_addTableColumn","toggleBlockHtmlMode","_syncStatefulButtons","activeId","blockToClear","_hideLinkPopover","_unbindFontSizeTracking","origLeft","origTop","dragging","onMouseMove","dx","dy","onMouseUp","parseInt","extraClass","command","sep","cmd","rangeCount","getRangeAt","surroundContents","px","collapsed","marker","fontSize","insertNode","nextRange","setStart","firstChild","span","extractContents","_currentSelectionFontSizePx","snapped","sizes","best","bestDelta","abs","_closestFontSize","focusNode","elNode","nodeType","ELEMENT_NODE","parentElement","_getSelectedBlockEl","raw","getComputedStyle","parseFloat","applyBtn","_restoreSavedLinkRange","querySelectorAll","a","target","rel","cloneRange","bottom","anchor","closest","_getCurrentTableContext","TEXT_NODE","maybeCell","ctx","currentRow","rowCells","from","colCount","newRow","td","indexOf","row","cells","ref","newCell","tagName","targetRowCells","focusCell","hasSelectionInEditor","active","queryCommandState","tableDisplay","_isSelectionInTable","InserterPanel","_searchInput","_listEl","_anchorEl","_onDocMouseDown","_onDocKeyDown","_savedRange","_mediaModal","_mediaModalCard","_mediaModalTitle","_mediaModalBody","_mediaModalResolver","_forceNewBlock","header","closeBtn","_renderList","_createMediaModal","open","anchorEl","forceNewBlock","_captureSelectionRange","_positionNearAnchor","_bindGlobalCloseHandlers","_unbindGlobalCloseHandlers","isOpen","_createBlockItem","cat","blockDef","info","_insertFromPopover","desiredLeft","innerWidth","desiredTop","innerHeight","commonAncestorContainer","_restoreSelectionRange","selectedId","selectedBlock","insertSingleBlockType","insertBlockAtSelection","source","_chooseMediaSource","_promptForMediaUrl","trimmed","_showToast","prompt","onChooseMediaSource","_openMediaSourceModal","card","_closeMediaModal","actions","urlBtn","cancelBtn","resolver","SettingsPanel","_activeTab","_postTab","_blockTab","_tagInput","_tags","_categories","_featuredImage","tabs","_postTabBtn","_blockTabBtn","_switchTab","_buildPostTab","_buildBlockTab","updateBlockSettings","_blockSettingsContent","section","fontSelect","l","lhInput","lineHeight","colorSection","textColors","swatch","background","bgColors","border","tab","summary","_section","_field","cats","catList","addCat","checked","tags","tagWrapper","tagInput","val","t","fi","fiArea","fiInput","exc","disc","_toggle","s","frag","createDocumentFragment","defaultOn","SlashMenu","_visible","_highlightIndex","_items","_targetBlock","_boundDocClick","destroy","editorRect","_filter","handleKeydown","_navigate","visible","_selectItem","dir","scrollIntoView","StatusBar","_wordEl","_charEl","_blockEl","_savedEl","bm","titleText","_titleEl","titleWords","words","chars","setSaved","PluginRegistry","_blockTypes","Map","_plugins","registerBlockType","definition","Error","fromHTML","isNew","has","set","_capitalize","unregisterBlockType","delete","getBlockType","get","getAllBlockTypes","obj","getCategories","registerCategory","registerPlugin","plugin","console","warn","unregisterPlugin","_plugin","initPlugins","init","keys","getPlugin","getPluginNames","destroyAll","charAt","toUpperCase","Differ","_baseline","_pendingPatches","setBaseline","_deepClone","diff","currentBlocks","patches","oldBlocks","newBlocks","oldMap","newMap","old","op","index","newBlock","oldBlock","changes","to","survivingOld","survivingNew","oldIdx","fromIndex","toIndex","_computeDiff","getChanges","hasChanges","reset","applyPatches","change","fromIdx","moved","CollaborativeManager","wsUrl","userId","token","debounceMs","reconnectMs","maxReconnectAttempts","_ws","_differ","_connected","_reconnectAttempts","_debounceTimer","_version","_pendingOps","_localChanges","_cleanup","connect","URL","searchParams","WebSocket","_setupWebSocket","_onLocalChange","disconnect","clearTimeout","onclose","isConnected","requestSync","_send","version","onopen","onmessage","msg","_handleMessage","reason","updatedBlocks","_sendLocalChanges","readyState","OPEN","send","_DOMPurify","require","default","DEFAULT_CONFIG","ALLOWED_TAGS","ALLOWED_ATTR","ALLOW_DATA_ATTR","ADD_ATTR","createSanitizer","config","mergedConfig","sanitize","allowedTags","Set","allowedAttrs","allowDataAttr","DOMParser","parseFromString","allElements","attributes","attr","removeAttribute","_fallbackSanitize","normalizeHTML","_normalizeNode","_isBlockElement","_normalizeElement","_isEmptyInline","sort","localeCompare","removeAttributeNode","_normalizeStyle","prop","vals","blocksToDelta","blockType","blockAttrs","ops","_htmlToOps","deltaToBlocks","entry","_opsToHTML","insert","_raw","_walkNodes","endsWith","parentAttrs","strike","sub","sup","highlight","getAttribute","isBlock","NBDEditor","selector","siteName","authorName","showStatusBar","autoSaveInterval","onChange","onSave","onPublish","sanitizeConfig","pluginRegistry","_sanitize","differ","blockRenderer","toolbar","slashMenu","_collaborative","_blocksContainer","_autoSaveTimer","_htmlEditorModal","_htmlEditorTextarea","_htmlEditorTitle","_htmlEditorBlockId","_boundGlobalKeydown","_handleGlobalKeydown","_init","canvas","role","_toast","_ariaLive","overflow","clip","_createHtmlEditorModal","_ensureAtLeastOneBlock","setInterval","_syncAllBlockContent","toLocaleTimeString","chunks","toAppend","tbContainer","tb","scrollLeft","requestAnimationFrame","_positionBlockToolbar","rendered","clickedContent","clickedEditable","clickedCell","clickedEditableIndex","editables","clickedCellPos","rowIndex","colIndex","nextCell","newWrapper","targetEditable","dd","toIdx","appender","plusIcon","targetId","_getInsertionTargetBlock","insertBlockAtEnd","getCaretRect","shiftKey","_getSelectionTableCell","_handleTableTab","nodeRect","prev","placeCaretAtStart","_generateSlug","slug","slugEl","getElementById","modal","_closeBlockHtmlEditor","textarea","spellcheck","_applyBlockHtmlEditor","ctrlKey","metaKey","_parseBlockFromHTML","fallbackType","wrap","first","firstElementChild","onlyOneElement","childElementCount","every","n","styleWidth","_readPercentWidth","mod","__sourceType","parsed","openBlockHtmlEditor","getTitle","setTitle","didBlockUndo","didBlockRedo","registered","getDelta","setDelta","sanitizeHTML","connectCollaborative","disconnectCollaborative","clearInterval","_announce","toolbarEl","toolbarRect","wrapperRect","shiftX","shouldPlaceBelow","currentCell","reverse","cellIndex","_placeCaretInCell","prevRowCells","nextRowCells","tbody","snippet","_snippetForType","_focusEditableTail","tail","lastElementChild","last","match","exec","ReactNBDEditor","React","forwardRef","props","onReady","editorOptions","hostRef","useRef","editorRef","lastContentRef","undefined","onChangeRef","onSaveRef","onPublishRef","debounceTimerRef","useEffect","initialOptions","nextContent","notify","currentHTML","useImperativeHandle","getInstance","opts"],"mappings":"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"}
|