rich-html-editor 0.2.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/LICENSE +21 -0
- package/README.md +263 -0
- package/dist/chunk-ZDGUOGND.mjs +441 -0
- package/dist/chunk-ZDGUOGND.mjs.map +1 -0
- package/dist/index.d.mts +73 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +1896 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1439 -0
- package/dist/index.mjs.map +1 -0
- package/dist/state-CZIMHTJ3.mjs +25 -0
- package/dist/state-CZIMHTJ3.mjs.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dom/styles.ts","../src/toolbar/toolbar.ts","../src/dom/candidates.ts","../src/dom/format.ts","../src/core/sanitizeURL.ts","../src/core/history.ts","../src/core/formatActions.ts","../src/dom/handlers.ts","../src/core/editor.ts"],"sourcesContent":["/**\r\n * Inject CSS styles into the document for editor UI\r\n *\r\n * Adds styling for:\r\n * - `.editor-editable-element`: Dashed outline for hoverable elements\r\n * - `.editor-active-element`: Solid green outline for active editing element\r\n *\r\n * Uses a style ID to prevent duplicate injections\r\n *\r\n * @param doc - Document to inject styles into\r\n */\r\nimport {\r\n STYLE_ID,\r\n CLASS_EDITABLE,\r\n CLASS_ACTIVE,\r\n HOVER_OUTLINE,\r\n ACTIVE_OUTLINE,\r\n TOOLBAR_ID,\r\n TOOLBAR_BG,\r\n TOOLBAR_BORDER,\r\n BUTTON_BORDER,\r\n BUTTON_ACTIVE_BG,\r\n BUTTON_BG,\r\n BUTTON_COLOR,\r\n INFO_COLOR,\r\n} from \"../core/constants\";\r\n\r\nexport function injectStyles(doc: Document): void {\r\n const styleId = STYLE_ID;\r\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\r\n const css = `\r\n.${CLASS_EDITABLE}{outline:2px dashed ${HOVER_OUTLINE};cursor:text}\r\n.${CLASS_ACTIVE}{outline:2px solid ${ACTIVE_OUTLINE};cursor:text}\r\n#${TOOLBAR_ID}{\r\n position: sticky;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n z-index: 9999;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n background: ${TOOLBAR_BG};\r\n border-bottom: 1px solid ${TOOLBAR_BORDER};\r\n font-family: inherit;\r\n box-shadow: 0 6px 18px rgba(2,6,23,0.08);\r\n backdrop-filter: blur(6px);\r\n /* Allow toolbar items to wrap onto multiple lines on narrow screens */\r\n flex-wrap: wrap;\r\n justify-content: flex-start;\r\n}\r\n#${TOOLBAR_ID} button{\r\n padding: 6px 8px;\r\n border: 1px solid ${BUTTON_BORDER};\r\n background: ${BUTTON_BG};\r\n color: ${BUTTON_COLOR};\r\n border-radius: 8px;\r\n font-weight: 500;\r\n cursor: pointer;\r\n transition: transform .12s ease, box-shadow .12s ease, background .12s ease;\r\n outline: none;\r\n margin-right: 2px;\r\n}\r\n#${TOOLBAR_ID} button[aria-pressed=\"true\"]{\r\n background: ${BUTTON_ACTIVE_BG};\r\n font-weight: 600;\r\n box-shadow: 0 6px 12px rgba(99,102,241,0.12);\r\n}\r\n#${TOOLBAR_ID} button:hover:not(:disabled){\r\n transform: translateY(-2px);\r\n box-shadow: 0 8px 20px rgba(2,6,23,0.08);\r\n}\r\n#${TOOLBAR_ID} select{\r\n padding: 6px 8px;\r\n border-radius: 8px;\r\n border: 1px solid ${BUTTON_BORDER};\r\n background: #fff;\r\n font-family: inherit;\r\n}\r\n#${TOOLBAR_ID} input[type=\"color\"]{\r\n border-radius: 8px;\r\n border: 1px solid ${BUTTON_BORDER};\r\n background: #fff;\r\n font-family: inherit;\r\n}\r\n#${TOOLBAR_ID} .color-input-label{\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 0;\r\n background: transparent;\r\n border: none;\r\n}\r\n\r\n/* Labeled color inputs (e.g. \"Text Color <input type=color>\") */\r\n#${TOOLBAR_ID} .color-label{\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 0;\r\n background: transparent;\r\n border: none;\r\n}\r\n#${TOOLBAR_ID} .color-input-label .color-icon{\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n#${TOOLBAR_ID} .text-color-icon{\r\n font-weight: 700;\r\n font-size: 14px;\r\n line-height: 1;\r\n display: inline-block;\r\n padding-bottom: 2px;\r\n border-bottom: 3px solid currentColor;\r\n transform-origin: center;\r\n}\r\n#${TOOLBAR_ID} .highlight-icon{\r\n width: 16px;\r\n height: 16px;\r\n display: inline-block;\r\n}\r\n#${TOOLBAR_ID} .color-icon svg{\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n}\r\n/* Text color wrapper: A with a small swatch on the right */\r\n#${TOOLBAR_ID} .text-color-wrapper{\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n}\r\n#${TOOLBAR_ID} .text-color-wrapper .text-A{\r\n font-weight: 700;\r\n font-size: 14px;\r\n line-height: 1;\r\n}\r\n#${TOOLBAR_ID} .text-color-wrapper .color-swatch{\r\n width: 12px;\r\n height: 12px;\r\n border-radius: 3px;\r\n border: 1px solid rgba(0,0,0,0.12);\r\n box-shadow: 0 1px 0 rgba(255,255,255,0.5) inset;\r\n background: currentColor;\r\n}\r\n\r\n/* Highlight wrapper: small colored bar under/behind the A to mimic highlighter */\r\n#${TOOLBAR_ID} .highlight-wrapper{\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n position: relative;\r\n}\r\n#${TOOLBAR_ID} .highlight-wrapper .highlight-bar{\r\n position: absolute;\r\n left: 0;\r\n right: 0;\r\n bottom: 2px;\r\n height: 8px;\r\n border-radius: 3px;\r\n background: #ffeb3b; /* default yellow */\r\n z-index: 0;\r\n}\r\n#${TOOLBAR_ID} .highlight-wrapper .text-A{\r\n position: relative;\r\n z-index: 1;\r\n font-weight: 700;\r\n font-size: 14px;\r\n line-height: 1;\r\n padding: 0 4px;\r\n}\r\n#${TOOLBAR_ID} span{\r\n color: ${INFO_COLOR};\r\n font-size: 90%;\r\n}\r\n\r\n/* Grouping and separators */\r\n#${TOOLBAR_ID} .toolbar-group{\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n}\r\n#${TOOLBAR_ID} .toolbar-group{\r\n /* groups may wrap internally to avoid overflow on narrow screens */\r\n flex-wrap: wrap;\r\n}\r\n/* Overflow button + menu styling */\r\n#${TOOLBAR_ID} .toolbar-overflow-btn{\r\n display: none;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 6px 8px;\r\n border-radius: 8px;\r\n border: 1px solid ${BUTTON_BORDER};\r\n background: ${BUTTON_BG};\r\n color: ${BUTTON_COLOR};\r\n font-weight: 600;\r\n}\r\n#${TOOLBAR_ID} .toolbar-overflow-menu{\r\n position: absolute;\r\n top: calc(100% + 6px);\r\n right: 12px;\r\n min-width: 160px;\r\n background: #fff;\r\n border: 1px solid rgba(15,23,42,0.06);\r\n border-radius: 8px;\r\n padding: 8px;\r\n box-shadow: 0 12px 40px rgba(2,6,23,0.12);\r\n display: flex;\r\n flex-direction: column;\r\n gap: 6px;\r\n z-index: 10000;\r\n}\r\n#${TOOLBAR_ID} .toolbar-overflow-menu[hidden]{\r\n display: none;\r\n}\r\n#${TOOLBAR_ID} .toolbar-sep{\r\n width: 1px;\r\n height: 28px;\r\n background: rgba(15,23,42,0.06);\r\n margin: 0 8px;\r\n border-radius: 1px;\r\n}\r\n#${TOOLBAR_ID} .toolbar-spacer{\r\n flex: 1 1 auto;\r\n}\r\n#${TOOLBAR_ID} button svg{\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n /* Default icon appearance */\r\n fill: none;\r\n}\r\n\r\n/* Active/pressed: switch to filled appearance */\r\n#${TOOLBAR_ID} button[aria-pressed=\"true\"] svg{\r\n fill: currentColor;\r\n}\r\n\r\n/* Focus and accessibility */\r\n#${TOOLBAR_ID} button:focus{\r\n outline: none;\r\n box-shadow: 0 0 0 4px rgba(99,102,241,0.12);\r\n}\r\n\r\n/* Disabled state */\r\n#${TOOLBAR_ID} button:disabled{\r\n opacity: 0.48;\r\n cursor: not-allowed;\r\n}\r\n/* Responsive tweaks: reduce spacing and allow horizontal scroll on very small screens */\r\n@media (max-width: 720px){\r\n #${TOOLBAR_ID}{\r\n padding: 6px 8px;\r\n gap: 6px;\r\n }\r\n #${TOOLBAR_ID} button,\r\n #${TOOLBAR_ID} select,\r\n #${TOOLBAR_ID} input[type=\"color\"]{\r\n padding: 4px 6px;\r\n border-radius: 6px;\r\n }\r\n /* Hide visual separators to save horizontal space */\r\n #${TOOLBAR_ID} .toolbar-sep{\r\n display: none;\r\n }\r\n /* Collapse labeled color text visually but preserve accessibility on the input */\r\n #${TOOLBAR_ID} .color-label{\r\n font-size: 0;\r\n }\r\n #${TOOLBAR_ID} .color-label input{\r\n font-size: initial;\r\n }\r\n}\r\n@media (max-width: 420px){\r\n /* On very small screens prefer a single-line scrollable toolbar */\r\n #${TOOLBAR_ID}{\r\n flex-wrap: nowrap;\r\n overflow-x: auto;\r\n -webkit-overflow-scrolling: touch;\r\n }\r\n #${TOOLBAR_ID} .toolbar-group{\r\n flex: 0 0 auto;\r\n }\r\n #${TOOLBAR_ID} button{ margin-right: 6px; }\r\n /* Show overflow button and hide the groups marked for collapse */\r\n #${TOOLBAR_ID} .toolbar-overflow-btn{\r\n display: inline-flex;\r\n }\r\n #${TOOLBAR_ID} .collapse-on-small{\r\n display: none;\r\n }\r\n}\r\n`;\r\n if (!styleEl) {\r\n styleEl = doc.createElement(\"style\");\r\n styleEl.id = styleId;\r\n doc.head.appendChild(styleEl);\r\n }\r\n styleEl.textContent = css;\r\n}\r\n","/**\r\n * Inject and render the formatting toolbar into the document\r\n *\r\n * Creates a sticky toolbar with:\r\n * - Text formatting buttons (Bold, Italic, Underline)\r\n * - Font and size selectors\r\n * - Undo/Redo buttons\r\n * - Link insertion button\r\n * - Color pickers (text and highlight)\r\n * - Text alignment buttons\r\n * - Selected element info display\r\n *\r\n * The toolbar is re-injected on every selection change to update state\r\n * (this is optimized for small toolbar size and few state changes)\r\n *\r\n * @param doc - Document to inject toolbar into\r\n * @param options - Toolbar configuration and callbacks\r\n */\r\nimport {\r\n TOOLBAR_ID,\r\n LABEL_BOLD,\r\n LABEL_ITALIC,\r\n LABEL_UNDERLINE,\r\n LABEL_STRIKETHROUGH,\r\n LABEL_UNDO,\r\n LABEL_REDO,\r\n LABEL_LINK,\r\n LABEL_ALIGN_LEFT,\r\n LABEL_ALIGN_CENTER,\r\n LABEL_ALIGN_RIGHT,\r\n FONT_OPTIONS,\r\n SIZE_OPTIONS,\r\n FORMAT_OPTIONS,\r\n PALETTE_SVG,\r\n TEXT_COLOR_ICON_HTML,\r\n HIGHLIGHT_ICON_HTML,\r\n} from \"../core/constants\";\r\n\r\nexport function injectToolbar(\r\n doc: Document,\r\n options: {\r\n onCommand: (command: string, value?: string) => void;\r\n canUndo: () => boolean;\r\n canRedo: () => boolean;\r\n onUndo: () => void;\r\n onRedo: () => void;\r\n getFormatState: () => {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n foreColor?: string | null;\r\n hiliteColor?: string | null;\r\n fontName?: string | null;\r\n fontSize?: string | null;\r\n formatBlock?: string | null;\r\n };\r\n getSelectedElementInfo: () => string | null;\r\n }\r\n) {\r\n const existing = doc.getElementById(TOOLBAR_ID);\r\n if (existing) existing.remove();\r\n\r\n const toolbar = doc.createElement(\"div\");\r\n toolbar.id = TOOLBAR_ID;\r\n // Accessibility: expose as a toolbar region and provide a readable label\r\n toolbar.setAttribute(\"role\", \"toolbar\");\r\n toolbar.setAttribute(\"aria-label\", \"Rich text editor toolbar\");\r\n\r\n // Styling moved to injected stylesheet (see src/dom/styles.ts)\r\n\r\n function makeButton(\r\n label: string,\r\n title: string,\r\n command: string,\r\n value?: string,\r\n isActive?: boolean,\r\n disabled?: boolean\r\n ) {\r\n const btn = doc.createElement(\"button\");\r\n btn.type = \"button\";\r\n // If caller provided an HTML label (e.g. \"<i>I</i>\"), render it as HTML.\r\n // Otherwise set textContent for safety.\r\n if (label && label.trim().startsWith(\"<\")) {\r\n btn.innerHTML = label;\r\n } else {\r\n btn.textContent = label;\r\n }\r\n btn.title = title;\r\n // Accessibility: aria-label + keyboard focusability + pressed state\r\n btn.setAttribute(\"aria-label\", title);\r\n if (typeof isActive !== \"undefined\")\r\n btn.setAttribute(\"aria-pressed\", String(!!isActive));\r\n btn.tabIndex = 0;\r\n // Visual appearance handled by stylesheet; use ARIA pressed for active state\r\n if (disabled) btn.disabled = true;\r\n btn.onclick = () => options.onCommand(command, value);\r\n // Keyboard activation: Enter or Space should trigger\r\n btn.addEventListener(\"keydown\", (ev) => {\r\n if (ev.key === \"Enter\" || ev.key === \" \") {\r\n ev.preventDefault();\r\n btn.click();\r\n }\r\n });\r\n return btn;\r\n }\r\n\r\n function makeSelect(\r\n title: string,\r\n command: string,\r\n optionsList: { label: string; value: string }[],\r\n initialValue?: string | null\r\n ) {\r\n const select = doc.createElement(\"select\");\r\n select.title = title;\r\n select.setAttribute(\"aria-label\", title);\r\n // Select styling handled in stylesheet\r\n select.appendChild(new Option(title, \"\", true, true));\r\n for (const opt of optionsList) {\r\n select.appendChild(new Option(opt.label, opt.value));\r\n }\r\n // set initial value if provided\r\n try {\r\n if (initialValue) select.value = initialValue;\r\n } catch (e) {\r\n /* ignore invalid value */\r\n }\r\n\r\n select.onchange = (e) => {\r\n const val = (e.target as HTMLSelectElement).value;\r\n options.onCommand(command, val);\r\n select.selectedIndex = 0;\r\n };\r\n return select;\r\n }\r\n\r\n function makeColorInput(\r\n title: string,\r\n command: string,\r\n initialColor?: string\r\n ) {\r\n /*\r\n const label = doc.createElement(\"label\");\r\n label.title = title;\r\n label.setAttribute(\"aria-label\", title);\r\n label.className = \"color-input-label\";\r\n // Icon element shown before the native color input. Use MS Word-like icons\r\n const iconWrap = doc.createElement(\"span\");\r\n iconWrap.className = \"color-icon\";\r\n iconWrap.setAttribute(\"aria-hidden\", \"true\");\r\n if (command === \"foreColor\") {\r\n iconWrap.innerHTML = TEXT_COLOR_ICON_HTML;\r\n } else if (command === \"hiliteColor\") {\r\n iconWrap.innerHTML = HIGHLIGHT_ICON_HTML;\r\n } else {\r\n iconWrap.innerHTML = PALETTE_SVG;\r\n }\r\n */\r\n\r\n const input = doc.createElement(\"input\");\r\n input.type = \"color\";\r\n input.className = \"toolbar-color-input\";\r\n // Wrap the native color input with a visible label so users can see\r\n // which control is for text color vs highlight.\r\n const wrapper = doc.createElement(\"label\");\r\n wrapper.className = \"color-label\";\r\n // Use the provided title as the label text (e.g. \"Text Color\")\r\n wrapper.appendChild(doc.createTextNode(title + \" \"));\r\n wrapper.appendChild(input);\r\n // Preserve the user's selection when the color picker opens (input steals focus)\r\n let savedRange: Range | null = null;\r\n input.addEventListener(\"pointerdown\", () => {\r\n const s = doc.getSelection();\r\n if (s && s.rangeCount) savedRange = s.getRangeAt(0).cloneRange();\r\n });\r\n input.onchange = (e) => {\r\n // Restore selection before applying the command\r\n try {\r\n const s = doc.getSelection();\r\n if (savedRange && s) {\r\n s.removeAllRanges();\r\n s.addRange(savedRange);\r\n }\r\n } catch (err) {\r\n // ignore restore errors\r\n }\r\n options.onCommand(command, (e.target as HTMLInputElement).value);\r\n // clear saved range after applying\r\n savedRange = null;\r\n };\r\n // Note: iconWrap/label are currently commented out above; operate on the\r\n // native color `input` only and set its value to match detected colors.\r\n function rgbToHex(input?: string | null): string | null {\r\n if (!input) return null;\r\n const v = input.trim();\r\n if (v.startsWith(\"#\")) {\r\n // Normalize short hex #abc -> #aabbcc\r\n if (v.length === 4) {\r\n return (\"#\" + v[1] + v[1] + v[2] + v[2] + v[3] + v[3]).toLowerCase();\r\n }\r\n return v.toLowerCase();\r\n }\r\n const rgbMatch = v.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/i);\r\n if (rgbMatch) {\r\n const r = Number(rgbMatch[1]);\r\n const g = Number(rgbMatch[2]);\r\n const b = Number(rgbMatch[3]);\r\n const hex =\r\n \"#\" +\r\n [r, g, b]\r\n .map((n) => n.toString(16).padStart(2, \"0\"))\r\n .join(\"\")\r\n .toLowerCase();\r\n return hex;\r\n }\r\n return null;\r\n }\r\n\r\n const setColor = (val?: string) => {\r\n if (!val) return;\r\n const hex = rgbToHex(val) || val;\r\n // set native input value if we have a hex color\r\n try {\r\n if (\r\n hex &&\r\n hex.startsWith(\"#\") &&\r\n (input as HTMLInputElement).value !== hex\r\n ) {\r\n (input as HTMLInputElement).value = hex;\r\n }\r\n } catch (e) {\r\n // ignore invalid value assignment\r\n }\r\n };\r\n // initialize from provided initialColor when available\r\n if (initialColor) setColor(initialColor);\r\n input.addEventListener(\"input\", (e) => {\r\n const val = (e.target as HTMLInputElement).value;\r\n setColor(val);\r\n });\r\n // Instead of using a label+icon, return the native input directly.\r\n // Forward title and ARIA to the input so accessibility is preserved.\r\n input.title = title;\r\n input.setAttribute(\"aria-label\", title);\r\n return wrapper;\r\n }\r\n\r\n const format = options.getFormatState();\r\n // Helpers: group wrapper and separator element\r\n function makeGroup() {\r\n const g = doc.createElement(\"div\");\r\n g.className = \"toolbar-group\";\r\n return g;\r\n }\r\n\r\n function makeSep() {\r\n const s = doc.createElement(\"div\");\r\n s.className = \"toolbar-sep\";\r\n return s;\r\n }\r\n\r\n // Section 1: Undo / Redo\r\n const undoBtn = makeButton(\r\n LABEL_UNDO,\r\n \"Undo\",\r\n \"undo\",\r\n undefined,\r\n false,\r\n !options.canUndo()\r\n );\r\n // Undo/Redo are handled by the history module — call handlers directly\r\n undoBtn.onclick = () => options.onUndo();\r\n\r\n const redoBtn = makeButton(\r\n LABEL_REDO,\r\n \"Redo\",\r\n \"redo\",\r\n undefined,\r\n false,\r\n !options.canRedo()\r\n );\r\n redoBtn.onclick = () => options.onRedo();\r\n\r\n const grp1 = makeGroup();\r\n grp1.appendChild(undoBtn);\r\n grp1.appendChild(redoBtn);\r\n toolbar.appendChild(grp1);\r\n toolbar.appendChild(makeSep());\r\n\r\n // Section 2: Format, Font & Size\r\n const grp2 = makeGroup();\r\n grp2.className = \"toolbar-group collapse-on-small\";\r\n grp2.appendChild(\r\n makeSelect(\r\n \"Format\",\r\n \"formatBlock\",\r\n FORMAT_OPTIONS,\r\n (format as any).formatBlock\r\n )\r\n );\r\n grp2.appendChild(\r\n makeSelect(\"Font\", \"fontName\", FONT_OPTIONS, (format as any).fontName)\r\n );\r\n grp2.appendChild(\r\n makeSelect(\"Size\", \"fontSize\", SIZE_OPTIONS, (format as any).fontSize)\r\n );\r\n toolbar.appendChild(grp2);\r\n toolbar.appendChild(makeSep());\r\n\r\n // Section 3: Bold, Italic, Underline, Strikethrough\r\n const grp3 = makeGroup();\r\n grp3.appendChild(\r\n makeButton(LABEL_BOLD, \"Bold\", \"bold\", undefined, format.bold)\r\n );\r\n grp3.appendChild(\r\n makeButton(LABEL_ITALIC, \"Italic\", \"italic\", undefined, format.italic)\r\n );\r\n grp3.appendChild(\r\n makeButton(\r\n LABEL_UNDERLINE,\r\n \"Underline\",\r\n \"underline\",\r\n undefined,\r\n format.underline\r\n )\r\n );\r\n grp3.appendChild(makeButton(LABEL_STRIKETHROUGH, \"Strikethrough\", \"strike\"));\r\n toolbar.appendChild(grp3);\r\n toolbar.appendChild(makeSep());\r\n\r\n // Section 4: Alignment\r\n const grp4 = makeGroup();\r\n grp4.appendChild(makeButton(LABEL_ALIGN_LEFT, \"Align left\", \"align\", \"left\"));\r\n grp4.appendChild(\r\n makeButton(LABEL_ALIGN_CENTER, \"Align center\", \"align\", \"center\")\r\n );\r\n grp4.appendChild(\r\n makeButton(LABEL_ALIGN_RIGHT, \"Align right\", \"align\", \"right\")\r\n );\r\n toolbar.appendChild(grp4);\r\n toolbar.appendChild(makeSep());\r\n\r\n // Section 5: Colors\r\n const grp5 = makeGroup();\r\n grp5.className = \"toolbar-group collapse-on-small\";\r\n grp5.appendChild(\r\n makeColorInput(\"Text color\", \"foreColor\", (format as any).foreColor)\r\n );\r\n grp5.appendChild(\r\n makeColorInput(\r\n \"Highlight color\",\r\n \"hiliteColor\",\r\n (format as any).hiliteColor\r\n )\r\n );\r\n toolbar.appendChild(grp5);\r\n toolbar.appendChild(makeSep());\r\n\r\n // Section 6: Link\r\n const grp6 = makeGroup();\r\n grp6.className = \"toolbar-group collapse-on-small\";\r\n grp6.appendChild(makeButton(LABEL_LINK, \"Insert link\", \"link\"));\r\n toolbar.appendChild(grp6);\r\n\r\n // Overflow menu button and floating menu for small screens\r\n const overflowBtn = doc.createElement(\"button\");\r\n overflowBtn.type = \"button\";\r\n overflowBtn.className = \"toolbar-overflow-btn\";\r\n overflowBtn.title = \"More\";\r\n overflowBtn.setAttribute(\"aria-label\", \"More toolbar actions\");\r\n overflowBtn.setAttribute(\"aria-haspopup\", \"true\");\r\n overflowBtn.setAttribute(\"aria-expanded\", \"false\");\r\n overflowBtn.tabIndex = 0;\r\n overflowBtn.innerHTML = \"⋯\";\r\n\r\n const overflowMenu = doc.createElement(\"div\");\r\n overflowMenu.className = \"toolbar-overflow-menu\";\r\n overflowMenu.setAttribute(\"role\", \"menu\");\r\n overflowMenu.hidden = true;\r\n\r\n function openOverflow() {\r\n overflowMenu.hidden = false;\r\n overflowBtn.setAttribute(\"aria-expanded\", \"true\");\r\n const first = overflowMenu.querySelector<HTMLElement>(\r\n \"button, select, input\"\r\n );\r\n first?.focus();\r\n }\r\n function closeOverflow() {\r\n overflowMenu.hidden = true;\r\n overflowBtn.setAttribute(\"aria-expanded\", \"false\");\r\n overflowBtn.focus();\r\n }\r\n\r\n overflowBtn.addEventListener(\"click\", (e) => {\r\n if (overflowMenu.hidden) openOverflow();\r\n else closeOverflow();\r\n });\r\n overflowBtn.addEventListener(\"keydown\", (e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n if (overflowMenu.hidden) openOverflow();\r\n else closeOverflow();\r\n }\r\n if (e.key === \"ArrowDown\") {\r\n e.preventDefault();\r\n if (overflowMenu.hidden) openOverflow();\r\n }\r\n });\r\n\r\n overflowMenu.addEventListener(\"keydown\", (e) => {\r\n if (e.key === \"Escape\") {\r\n e.preventDefault();\r\n closeOverflow();\r\n }\r\n });\r\n doc.addEventListener(\"pointerdown\", (ev) => {\r\n if (\r\n !overflowMenu.hidden &&\r\n !overflowMenu.contains(ev.target as Node) &&\r\n ev.target !== overflowBtn\r\n ) {\r\n closeOverflow();\r\n }\r\n });\r\n\r\n // Populate overflow menu with duplicates of the collapsed controls\r\n overflowMenu.appendChild(\r\n makeSelect(\r\n \"Format\",\r\n \"formatBlock\",\r\n FORMAT_OPTIONS,\r\n (format as any).formatBlock\r\n )\r\n );\r\n overflowMenu.appendChild(\r\n makeSelect(\"Font\", \"fontName\", FONT_OPTIONS, (format as any).fontName)\r\n );\r\n overflowMenu.appendChild(\r\n makeSelect(\"Size\", \"fontSize\", SIZE_OPTIONS, (format as any).fontSize)\r\n );\r\n overflowMenu.appendChild(\r\n makeColorInput(\"Text color\", \"foreColor\", (format as any).foreColor)\r\n );\r\n overflowMenu.appendChild(\r\n makeColorInput(\r\n \"Highlight color\",\r\n \"hiliteColor\",\r\n (format as any).hiliteColor\r\n )\r\n );\r\n overflowMenu.appendChild(makeButton(LABEL_LINK, \"Insert link\", \"link\"));\r\n\r\n const overflowWrap = makeGroup();\r\n overflowWrap.className = \"toolbar-group toolbar-overflow-wrap\";\r\n overflowWrap.appendChild(overflowBtn);\r\n overflowWrap.appendChild(overflowMenu);\r\n toolbar.appendChild(overflowWrap);\r\n\r\n // const info = doc.createElement(\"span\");\r\n // // Info styles moved to stylesheet\r\n // info.textContent = options.getSelectedElementInfo()\r\n // ? `Selected: ${options.getSelectedElementInfo()}`\r\n // : \"Click any highlighted element to edit\";\r\n // toolbar.appendChild(info);\r\n\r\n // Keyboard navigation for toolbar (ArrowLeft/ArrowRight/Home/End)\r\n toolbar.addEventListener(\"keydown\", (e) => {\r\n const focusable = Array.from(\r\n toolbar.querySelectorAll<HTMLElement>(\"button, select, input, [tabindex]\")\r\n ).filter((el) => !el.hasAttribute(\"disabled\"));\r\n if (!focusable.length) return;\r\n const idx = focusable.indexOf(document.activeElement as HTMLElement);\r\n if (e.key === \"ArrowRight\") {\r\n e.preventDefault();\r\n const next =\r\n focusable[Math.min(focusable.length - 1, Math.max(0, idx + 1))];\r\n next?.focus();\r\n } else if (e.key === \"ArrowLeft\") {\r\n e.preventDefault();\r\n const prev = focusable[Math.max(0, idx - 1)] || focusable[0];\r\n prev?.focus();\r\n } else if (e.key === \"Home\") {\r\n e.preventDefault();\r\n focusable[0].focus();\r\n } else if (e.key === \"End\") {\r\n e.preventDefault();\r\n focusable[focusable.length - 1].focus();\r\n }\r\n });\r\n\r\n doc.body.insertBefore(toolbar, doc.body.firstChild);\r\n}\r\n","/**\r\n * Check if an element can be edited\r\n *\r\n * Valid elements: Text container tags (p, div, section, etc.)\r\n * Invalid elements: HTML structure tags, inputs, scripts, styles\r\n *\r\n * @param el - Element to check\r\n * @returns True if element is a valid editable candidate\r\n */\r\nexport function isEditableCandidate(el: HTMLElement | null): boolean {\r\n if (!el) return false;\r\n const tag = el.tagName;\r\n const DISALLOWED = [\r\n \"HTML\",\r\n \"HEAD\",\r\n \"BODY\",\r\n \"SCRIPT\",\r\n \"STYLE\",\r\n \"LINK\",\r\n \"META\",\r\n \"NOSCRIPT\",\r\n ];\r\n if (DISALLOWED.includes(tag)) return false;\r\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return false;\r\n return true;\r\n}\r\n","/**\r\n * Compute the current formatting state of selected text\r\n *\r\n * Detects bold, italic, and underline formatting based on:\r\n * - DOM element tags (strong, em, u)\r\n * - CSS computed styles (fontWeight, fontStyle, textDecoration)\r\n *\r\n * @param doc - Document context\r\n * @returns Object with boolean flags for bold, italic, underline\r\n */\r\nexport function computeFormatState(doc: Document): {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n foreColor: string | null;\r\n hiliteColor: string | null;\r\n fontName: string | null;\r\n fontSize: string | null;\r\n formatBlock: string | null;\r\n} {\r\n try {\r\n const s = doc.getSelection();\r\n let el: HTMLElement | null = null;\r\n if (s && s.anchorNode)\r\n el =\r\n s.anchorNode.nodeType === Node.ELEMENT_NODE\r\n ? (s.anchorNode as HTMLElement)\r\n : (s.anchorNode.parentElement as HTMLElement);\r\n if (!el)\r\n return {\r\n bold: false,\r\n italic: false,\r\n underline: false,\r\n foreColor: null,\r\n hiliteColor: null,\r\n fontName: null,\r\n fontSize: null,\r\n formatBlock: null,\r\n };\r\n const computed = doc.defaultView?.getComputedStyle(el) as\r\n | CSSStyleDeclaration\r\n | undefined;\r\n const bold = !!(\r\n el.closest(\"strong, b\") ||\r\n (computed &&\r\n (computed.fontWeight === \"700\" || Number(computed.fontWeight) >= 700))\r\n );\r\n const italic = !!(\r\n el.closest(\"em, i\") ||\r\n (computed && computed.fontStyle === \"italic\")\r\n );\r\n const underline = !!(\r\n el.closest(\"u\") ||\r\n (computed && (computed.textDecorationLine || \"\").includes(\"underline\"))\r\n );\r\n // Try to detect text color and highlight (background) color at the selection\r\n const foreColor =\r\n (el.closest(\"font[color]\") as HTMLElement | null)?.getAttribute(\r\n \"color\"\r\n ) ||\r\n (computed && computed.color) ||\r\n null;\r\n // Background color may come from a <mark> element or computed background-color\r\n const mark = el.closest(\"mark\") as HTMLElement | null;\r\n const hiliteColor =\r\n (mark && (mark.getAttribute(\"style\") || \"\")) ||\r\n (computed &&\r\n computed.backgroundColor &&\r\n computed.backgroundColor !== \"rgba(0, 0, 0, 0)\"\r\n ? computed.backgroundColor\r\n : null);\r\n\r\n // detect font name + size from computed style\r\n const fontName = (computed && computed.fontFamily) || null;\r\n const fontSize = (computed && computed.fontSize) || null;\r\n // detect block ancestor (paragraph, heading etc.)\r\n let blockEl: HTMLElement | null = el;\r\n while (blockEl && blockEl.parentElement) {\r\n const tag = blockEl.tagName;\r\n if (\r\n [\r\n \"P\",\r\n \"DIV\",\r\n \"SECTION\",\r\n \"ARTICLE\",\r\n \"LI\",\r\n \"TD\",\r\n \"BLOCKQUOTE\",\r\n \"H1\",\r\n \"H2\",\r\n \"H3\",\r\n \"H4\",\r\n \"H5\",\r\n \"H6\",\r\n ].includes(tag)\r\n ) {\r\n break;\r\n }\r\n blockEl = blockEl.parentElement as HTMLElement | null;\r\n }\r\n const formatBlock = blockEl ? blockEl.tagName.toLowerCase() : null;\r\n\r\n return {\r\n bold,\r\n italic,\r\n underline,\r\n foreColor,\r\n hiliteColor,\r\n fontName,\r\n fontSize,\r\n formatBlock,\r\n };\r\n } catch (err) {\r\n return {\r\n bold: false,\r\n italic: false,\r\n underline: false,\r\n foreColor: null,\r\n hiliteColor: null,\r\n fontName: null,\r\n fontSize: null,\r\n formatBlock: null,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Get a human-readable label for an element\r\n *\r\n * Format: `tagname#id.class`\r\n * Example: `p#intro.highlight` or `div.container`\r\n *\r\n * @param el - HTML element to label\r\n * @returns Label string or null if element is null\r\n */\r\nexport function getElementLabel(el: HTMLElement | null): string | null {\r\n if (!el) return null;\r\n const id = el.id ? `#${el.id}` : \"\";\r\n const cls = el.className ? `.${String(el.className).split(\" \")[0]}` : \"\";\r\n const tag = el.tagName.toLowerCase();\r\n return `${tag}${id}${cls}`;\r\n}\r\n","export function sanitizeURL(url: string): string {\r\n if (!url) return \"\";\r\n const trimmed = url.trim();\r\n if (!trimmed) return \"\";\r\n if (\r\n trimmed.toLowerCase().startsWith(\"javascript:\") ||\r\n trimmed.toLowerCase().startsWith(\"data:\")\r\n ) {\r\n console.warn(\"Blocked potentially dangerous URL protocol\");\r\n return \"\";\r\n }\r\n if (!trimmed.startsWith(\"http\") && !trimmed.startsWith(\"#\")) {\r\n return \"https://\" + trimmed;\r\n }\r\n return trimmed;\r\n}\r\n","import {\r\n _getDoc,\r\n _getUndoStack,\r\n _getRedoStack,\r\n _setUndoStack,\r\n _setRedoStack,\r\n} from \"./state\";\r\n\r\nimport { sanitizeHtml } from \"../utils/sanitize\";\r\nimport { injectStyles } from \"../dom/styles\";\r\n\r\nexport function handleUndo() {\r\n try {\r\n const doc = _getDoc();\r\n if (!doc) {\r\n console.warn(\r\n \"[rich-html-editor] handleUndo called before initialization\"\r\n );\r\n return;\r\n }\r\n if (_getUndoStack().length < 2) return;\r\n const undoStack = _getUndoStack();\r\n const redoStack = _getRedoStack();\r\n const current = undoStack.pop()!;\r\n redoStack.push(current);\r\n const prev = undoStack[undoStack.length - 1];\r\n if (!doc.documentElement) {\r\n throw new Error(\"Document is missing documentElement\");\r\n }\r\n // Sanitize the snapshot and extract only the body content so we\r\n // avoid overwriting head/link/style nodes that may contain page\r\n // or editor styles. Replacing only `document.body` preserves those\r\n // nodes while still restoring user content.\r\n const safe = sanitizeHtml(prev.replace(/^<!doctype html>\\n?/i, \"\"), doc);\r\n try {\r\n const parser = new DOMParser();\r\n const parsed = parser.parseFromString(safe, \"text/html\");\r\n if (parsed && parsed.body && doc.body) {\r\n // Prefer selective restoration: if the snapshot contains elements\r\n // marked with `data-rhe-id`, restore only those elements so we do\r\n // not clobber page-level UI (headers, tabs, carousel scripts).\r\n const parsedEls = parsed.body.querySelectorAll(\"[data-rhe-id]\");\r\n if (parsedEls && parsedEls.length) {\r\n const loadPromises: Promise<void>[] = [];\r\n parsedEls.forEach((pe) => {\r\n const id = pe.getAttribute(\"data-rhe-id\");\r\n if (!id) return;\r\n const local = doc.body.querySelector(`[data-rhe-id=\"${id}\"]`);\r\n if (!local) return;\r\n // Copy non-identifying attributes from parsed element to local\r\n try {\r\n Array.from(local.attributes).forEach((a) => {\r\n if (a.name !== \"data-rhe-id\") local.removeAttribute(a.name);\r\n });\r\n Array.from(pe.attributes).forEach((a) => {\r\n if (a.name !== \"data-rhe-id\")\r\n local.setAttribute(a.name, a.value);\r\n });\r\n } catch (err) {\r\n /* ignore attribute copy errors */\r\n }\r\n // Replace innerHTML of the editable region only\r\n try {\r\n local.innerHTML = pe.innerHTML;\r\n } catch (err) {\r\n /* ignore innerHTML set errors */\r\n }\r\n // Recreate preserved script placeholders inside the parsed element\r\n try {\r\n const placeholders = pe.querySelectorAll(\"[data-rhe-script]\");\r\n placeholders.forEach((ph) => {\r\n const encoded = ph.getAttribute(\"data-rhe-script\") || \"\";\r\n let code = \"\";\r\n try {\r\n code =\r\n typeof atob !== \"undefined\"\r\n ? decodeURIComponent(escape(atob(encoded)))\r\n : decodeURIComponent(encoded);\r\n } catch (e) {\r\n try {\r\n code = decodeURIComponent(encoded);\r\n } catch (er) {\r\n code = \"\";\r\n }\r\n }\r\n const attrsRaw = ph.getAttribute(\"data-rhe-script-attrs\");\r\n let attrs: Record<string, string> = {};\r\n if (attrsRaw) {\r\n try {\r\n attrs = JSON.parse(decodeURIComponent(attrsRaw));\r\n } catch (e) {\r\n attrs = {};\r\n }\r\n }\r\n const parentId = ph.getAttribute(\"data-rhe-script-parent\");\r\n try {\r\n const s = doc.createElement(\"script\");\r\n try {\r\n s.type = \"text/javascript\";\r\n (s as any).async = false;\r\n } catch (err) {\r\n /* ignore */\r\n }\r\n Object.keys(attrs).forEach((k) =>\r\n s.setAttribute(k, attrs[k])\r\n );\r\n if (attrs.src) {\r\n const p = new Promise<void>((resolve) => {\r\n s.addEventListener(\"load\", () => resolve());\r\n s.addEventListener(\"error\", () => resolve());\r\n });\r\n loadPromises.push(p);\r\n s.src = attrs.src;\r\n } else {\r\n s.textContent = code;\r\n }\r\n if (parentId === \"head\") {\r\n doc.head.appendChild(s);\r\n } else {\r\n const target = doc.body.querySelector(\r\n `[data-rhe-id=\"${parentId}\"]`\r\n );\r\n if (target) target.appendChild(s);\r\n else doc.body.appendChild(s);\r\n }\r\n } catch (e) {\r\n /* ignore script injection errors */\r\n }\r\n });\r\n } catch (e) {\r\n /* ignore placeholder processing errors */\r\n }\r\n });\r\n try {\r\n if (loadPromises.length) {\r\n const waiter = (Promise as any).allSettled\r\n ? (Promise as any).allSettled(loadPromises)\r\n : Promise.all(\r\n loadPromises.map((p) => p.catch(() => undefined))\r\n );\r\n waiter.then(() => {\r\n try {\r\n doc.dispatchEvent(new Event(\"rhe:scripts-restored\"));\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n });\r\n } else {\r\n try {\r\n doc.dispatchEvent(new Event(\"rhe:scripts-restored\"));\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n }\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n } else {\r\n // No markers present — fallback to previous behavior of replacing\r\n // the body contents. This preserves backward compatibility.\r\n doc.body.innerHTML = parsed.body.innerHTML;\r\n }\r\n } else {\r\n // Fallback to replacing the whole documentElement if body is missing\r\n doc.documentElement.innerHTML = safe;\r\n }\r\n } catch (err) {\r\n // On any parse error, fall back to previous behavior\r\n doc.documentElement.innerHTML = safe;\r\n }\r\n\r\n // Re-inject editor styles (toolbar/style) and notify listeners so the\r\n // toolbar is restored and selectionchange handlers run.\r\n injectStyles(doc);\r\n try {\r\n doc.dispatchEvent(new Event(\"selectionchange\"));\r\n } catch (err) {\r\n /* ignore dispatch errors */\r\n }\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Undo failed:\", message);\r\n }\r\n}\r\n\r\nexport function handleRedo() {\r\n try {\r\n const doc = _getDoc();\r\n if (!doc) {\r\n console.warn(\r\n \"[rich-html-editor] handleRedo called before initialization\"\r\n );\r\n return;\r\n }\r\n if (!_getRedoStack().length) return;\r\n const undoStack = _getUndoStack();\r\n const redoStack = _getRedoStack();\r\n const next = redoStack.pop()!;\r\n undoStack.push(next);\r\n if (!doc.documentElement) {\r\n throw new Error(\"Document is missing documentElement\");\r\n }\r\n const safeNext = sanitizeHtml(\r\n next.replace(/^<!doctype html>\\n?/i, \"\"),\r\n doc\r\n );\r\n try {\r\n const parser = new DOMParser();\r\n const parsed = parser.parseFromString(safeNext, \"text/html\");\r\n if (parsed && parsed.body && doc.body) {\r\n const parsedEls = parsed.body.querySelectorAll(\"[data-rhe-id]\");\r\n if (parsedEls && parsedEls.length) {\r\n const loadPromises: Promise<void>[] = [];\r\n parsedEls.forEach((pe) => {\r\n const id = pe.getAttribute(\"data-rhe-id\");\r\n if (!id) return;\r\n const local = doc.body.querySelector(`[data-rhe-id=\"${id}\"]`);\r\n if (!local) return;\r\n try {\r\n Array.from(local.attributes).forEach((a) => {\r\n if (a.name !== \"data-rhe-id\") local.removeAttribute(a.name);\r\n });\r\n Array.from(pe.attributes).forEach((a) => {\r\n if (a.name !== \"data-rhe-id\")\r\n local.setAttribute(a.name, a.value);\r\n });\r\n } catch (err) {\r\n /* ignore */\r\n }\r\n try {\r\n local.innerHTML = pe.innerHTML;\r\n } catch (err) {\r\n /* ignore */\r\n }\r\n try {\r\n const placeholders = pe.querySelectorAll(\"[data-rhe-script]\");\r\n placeholders.forEach((ph) => {\r\n const encoded = ph.getAttribute(\"data-rhe-script\") || \"\";\r\n let code = \"\";\r\n try {\r\n code =\r\n typeof atob !== \"undefined\"\r\n ? decodeURIComponent(escape(atob(encoded)))\r\n : decodeURIComponent(encoded);\r\n } catch (e) {\r\n try {\r\n code = decodeURIComponent(encoded);\r\n } catch (er) {\r\n code = \"\";\r\n }\r\n }\r\n const attrsRaw = ph.getAttribute(\"data-rhe-script-attrs\");\r\n let attrs: Record<string, string> = {};\r\n if (attrsRaw) {\r\n try {\r\n attrs = JSON.parse(decodeURIComponent(attrsRaw));\r\n } catch (e) {\r\n attrs = {};\r\n }\r\n }\r\n const parentId = ph.getAttribute(\"data-rhe-script-parent\");\r\n try {\r\n const s = doc.createElement(\"script\");\r\n try {\r\n s.type = \"text/javascript\";\r\n (s as any).async = false;\r\n } catch (err) {\r\n /* ignore */\r\n }\r\n Object.keys(attrs).forEach((k) =>\r\n s.setAttribute(k, attrs[k])\r\n );\r\n if (attrs.src) {\r\n const p = new Promise<void>((resolve) => {\r\n s.addEventListener(\"load\", () => resolve());\r\n s.addEventListener(\"error\", () => resolve());\r\n });\r\n loadPromises.push(p);\r\n s.src = attrs.src;\r\n } else {\r\n s.textContent = code;\r\n }\r\n if (parentId === \"head\") {\r\n doc.head.appendChild(s);\r\n } else {\r\n const target = doc.body.querySelector(\r\n `[data-rhe-id=\"${parentId}\"]`\r\n );\r\n if (target) target.appendChild(s);\r\n else doc.body.appendChild(s);\r\n }\r\n } catch (e) {\r\n /* ignore script injection errors */\r\n }\r\n });\r\n } catch (e) {\r\n /* ignore placeholder processing errors */\r\n }\r\n });\r\n try {\r\n if (loadPromises.length) {\r\n const waiter = (Promise as any).allSettled\r\n ? (Promise as any).allSettled(loadPromises)\r\n : Promise.all(\r\n loadPromises.map((p) => p.catch(() => undefined))\r\n );\r\n waiter.then(() => {\r\n try {\r\n doc.dispatchEvent(new Event(\"rhe:scripts-restored\"));\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n });\r\n } else {\r\n try {\r\n doc.dispatchEvent(new Event(\"rhe:scripts-restored\"));\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n }\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n } else {\r\n doc.body.innerHTML = parsed.body.innerHTML;\r\n }\r\n } else {\r\n doc.documentElement.innerHTML = safeNext;\r\n }\r\n } catch (err) {\r\n doc.documentElement.innerHTML = safeNext;\r\n }\r\n\r\n // Re-inject styles and notify listeners so toolbar/styles are restored\r\n injectStyles(doc);\r\n try {\r\n doc.dispatchEvent(new Event(\"selectionchange\"));\r\n } catch (err) {\r\n /* ignore dispatch errors */\r\n }\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Redo failed:\", message);\r\n }\r\n}\r\n","import { _getDoc, pushStandaloneSnapshot } from \"./state\";\r\nimport { sanitizeHtml } from \"../utils/sanitize\";\r\nimport { sanitizeURL } from \"./sanitizeURL\";\r\n\r\nexport function handleToolbarCommand(command: string, value?: string) {\r\n try {\r\n const doc = _getDoc();\r\n if (!doc) {\r\n console.warn(\r\n \"[rich-html-editor] handleToolbarCommand called before initialization\"\r\n );\r\n return;\r\n }\r\n if (command === \"undo\") return; // delegated to history module\r\n if (command === \"redo\") return; // delegated to history module\r\n if (command === \"link\") {\r\n const url = window.prompt(\"Enter URL (https://...):\", \"https://\");\r\n if (url) {\r\n const sanitized = sanitizeURL(url);\r\n if (sanitized) applyStandaloneCommand(\"link\", sanitized);\r\n }\r\n return;\r\n }\r\n applyStandaloneCommand(command, value);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Command handler failed:\", message);\r\n }\r\n}\r\n\r\nexport function applyStandaloneCommand(command: string, value?: string) {\r\n try {\r\n const doc = _getDoc();\r\n if (!doc) {\r\n console.warn(\r\n \"[rich-html-editor] applyStandaloneCommand called before initialization\"\r\n );\r\n return;\r\n }\r\n\r\n if (command === \"bold\") wrapSelectionWithElement(doc, \"strong\");\r\n else if (command === \"italic\") wrapSelectionWithElement(doc, \"em\");\r\n else if (command === \"underline\") wrapSelectionWithElement(doc, \"u\");\r\n else if (command === \"strike\") wrapSelectionWithElement(doc, \"s\");\r\n else if (command === \"fontName\")\r\n wrapSelectionWithElement(doc, \"span\", { fontFamily: value as any });\r\n else if (command === \"fontSize\") {\r\n // Accept numeric font-size values (e.g. \"12\", \"16\") and apply as px.\r\n const raw = value || \"14\";\r\n const n = parseInt(raw, 10);\r\n const sz = Number.isFinite(n) ? `${n}px` : raw;\r\n wrapSelectionWithElement(doc, \"span\", { fontSize: sz as any });\r\n } else if (command === \"link\") {\r\n const sel = doc.getSelection();\r\n if (!sel || !sel.rangeCount) return;\r\n const range = sel.getRangeAt(0);\r\n const content = range.extractContents();\r\n const a = doc.createElement(\"a\");\r\n a.href = sanitizeURL(value || \"#\");\r\n a.appendChild(content);\r\n range.insertNode(a);\r\n } else if (command === \"foreColor\")\r\n wrapSelectionWithElement(doc, \"span\", { color: value as any });\r\n else if (command === \"hiliteColor\")\r\n wrapSelectionWithElement(doc, \"span\", { backgroundColor: value as any });\r\n else if (command === \"align\") {\r\n const sel = doc.getSelection();\r\n const node = sel?.anchorNode || null;\r\n const block = findBlockAncestor(node);\r\n if (block) block.style.textAlign = value || \"left\";\r\n else wrapSelectionWithElement(doc, \"div\", { textAlign: value as any });\r\n } else if (command === \"formatBlock\") {\r\n // Change block-level element to selected tag (p, h1..h6)\r\n const sel = doc.getSelection();\r\n const node = sel?.anchorNode || null;\r\n const block = findBlockAncestor(node);\r\n const tag = (value || \"p\").toLowerCase();\r\n if (block && block.parentElement) {\r\n // Replace existing block with new block of desired tag\r\n const newEl = doc.createElement(tag);\r\n // Preserve inline styles?\r\n newEl.className = (block as HTMLElement).className || \"\";\r\n while (block.firstChild) newEl.appendChild(block.firstChild);\r\n block.parentElement.replaceChild(newEl, block);\r\n } else {\r\n // Wrap selection in the block tag\r\n wrapSelectionWithElement(doc, tag);\r\n }\r\n }\r\n pushStandaloneSnapshot();\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Apply command failed:\", message);\r\n }\r\n}\r\n\r\nfunction wrapSelectionWithElement(\r\n doc: Document,\r\n tagName: string,\r\n style?: Partial<CSSStyleDeclaration>\r\n): void {\r\n const sel = doc.getSelection();\r\n if (!sel) return;\r\n if (!sel.rangeCount) return;\r\n const range = sel.getRangeAt(0);\r\n if (range.collapsed) {\r\n const el = doc.createElement(tagName);\r\n if (style) Object.assign(el.style, style as any);\r\n const zw = doc.createTextNode(\"\\u200B\");\r\n el.appendChild(zw);\r\n range.insertNode(el);\r\n const newRange = doc.createRange();\r\n newRange.setStart(zw, 1);\r\n newRange.collapse(true);\r\n sel.removeAllRanges();\r\n sel.addRange(newRange);\r\n return;\r\n }\r\n const content = range.extractContents();\r\n const wrapper = doc.createElement(tagName);\r\n if (style) Object.assign(wrapper.style, style as any);\r\n wrapper.appendChild(content);\r\n range.insertNode(wrapper);\r\n sel.removeAllRanges();\r\n const newRange = doc.createRange();\r\n newRange.selectNodeContents(wrapper);\r\n sel.addRange(newRange);\r\n}\r\n\r\nfunction findBlockAncestor(node: Node | null): HTMLElement | null {\r\n let n = node as Node | null;\r\n const BLOCKS = [\r\n \"P\",\r\n \"DIV\",\r\n \"SECTION\",\r\n \"ARTICLE\",\r\n \"LI\",\r\n \"TD\",\r\n \"BLOCKQUOTE\",\r\n \"H1\",\r\n \"H2\",\r\n \"H3\",\r\n \"H4\",\r\n \"H5\",\r\n \"H6\",\r\n ];\r\n while (n) {\r\n if (n.nodeType === Node.ELEMENT_NODE) {\r\n const el = n as HTMLElement;\r\n if (BLOCKS.includes(el.tagName)) return el;\r\n }\r\n n = n.parentNode;\r\n }\r\n return null;\r\n}\r\n","import {\r\n _getCurrentEditable,\r\n _setCurrentEditable,\r\n pushStandaloneSnapshot,\r\n _getUndoStack,\r\n _getRedoStack,\r\n} from \"../core/state\";\r\nimport { isEditableCandidate } from \"./candidates\";\r\nimport { injectToolbar } from \"../toolbar/toolbar\";\r\nimport { computeFormatState, getElementLabel } from \"./format\";\r\nimport { handleToolbarCommand, handleUndo, handleRedo } from \"../core/commands\";\r\nimport { CLASS_ACTIVE } from \"../core/constants\";\r\n\r\n/**\r\n * Attach DOM event handlers to the document\r\n *\r\n * Handles:\r\n * - Click: Enables editing on valid elements\r\n * - Selection change: Updates toolbar state\r\n * - Input: Creates undo/redo snapshots\r\n *\r\n * @param doc - Document to attach handlers to\r\n */\r\nexport function attachStandaloneHandlers(doc: Document) {\r\n // Assign stable data-rhe-id markers to likely editable candidates so\r\n // snapshots include identifiers for selective restoration. Limit the\r\n // selector to common content containers to avoid a full DOM walk.\r\n try {\r\n const selector = [\r\n \"p\",\r\n \"div\",\r\n \"section\",\r\n \"article\",\r\n \"header\",\r\n \"footer\",\r\n \"aside\",\r\n \"nav\",\r\n \"span\",\r\n \"h1\",\r\n \"h2\",\r\n \"h3\",\r\n \"h4\",\r\n \"h5\",\r\n \"h6\",\r\n \"li\",\r\n \"figure\",\r\n \"figcaption\",\r\n \"blockquote\",\r\n \"pre\",\r\n \"code\",\r\n ].join(\",\");\r\n const candidates = Array.from(\r\n doc.querySelectorAll<HTMLElement>(selector)\r\n ).filter((el) => isEditableCandidate(el));\r\n candidates.forEach((target) => {\r\n if (!target.hasAttribute(\"data-rhe-id\")) {\r\n const uid = `rhe-init-${Date.now()}-${Math.random()\r\n .toString(36)\r\n .slice(2, 7)}`;\r\n try {\r\n target.setAttribute(\"data-rhe-id\", uid);\r\n } catch (err) {\r\n /* ignore */\r\n }\r\n }\r\n });\r\n } catch (err) {\r\n /* ignore initialization errors */\r\n }\r\n\r\n doc.addEventListener(\r\n \"click\",\r\n (e) => {\r\n const target = e.target as HTMLElement;\r\n if (!isEditableCandidate(target)) return;\r\n if (_getCurrentEditable() && _getCurrentEditable() !== target) {\r\n _getCurrentEditable()?.removeAttribute(\"contenteditable\");\r\n _getCurrentEditable()?.classList.remove(CLASS_ACTIVE);\r\n }\r\n // Ensure the editable element has a stable identifier so snapshots\r\n // can restore only the editable region without touching the rest\r\n // of the page (header, nav, scripts, etc.). Use a data attribute\r\n // to avoid clashing with page ids.\r\n if (!target.hasAttribute(\"data-rhe-id\")) {\r\n const uid = `rhe-${Date.now()}-${Math.random()\r\n .toString(36)\r\n .slice(2, 7)}`;\r\n try {\r\n target.setAttribute(\"data-rhe-id\", uid);\r\n } catch (err) {\r\n /* ignore attribute set errors */\r\n }\r\n }\r\n _setCurrentEditable(target);\r\n target.classList.add(CLASS_ACTIVE);\r\n target.setAttribute(\"contenteditable\", \"true\");\r\n target.focus();\r\n },\r\n true\r\n );\r\n doc.addEventListener(\"selectionchange\", () => {\r\n injectToolbar(doc, {\r\n onCommand: handleToolbarCommand,\r\n canUndo: () => _getUndoStack().length > 1,\r\n canRedo: () => _getRedoStack().length > 0,\r\n onUndo: handleUndo,\r\n onRedo: handleRedo,\r\n getFormatState: () => computeFormatState(doc),\r\n getSelectedElementInfo: () => getElementLabel(_getCurrentEditable()),\r\n });\r\n });\r\n doc.addEventListener(\"input\", () => pushStandaloneSnapshot(), true);\r\n\r\n // Keyboard shortcuts for common formatting and undo/redo\r\n doc.addEventListener(\r\n \"keydown\",\r\n (e) => {\r\n const meta = e.ctrlKey || e.metaKey;\r\n if (!meta) return;\r\n const key = e.key.toLowerCase();\r\n // Bold: Ctrl/Cmd+B\r\n if (key === \"b\") {\r\n e.preventDefault();\r\n handleToolbarCommand(\"bold\");\r\n return;\r\n }\r\n // Italic: Ctrl/Cmd+I\r\n if (key === \"i\") {\r\n e.preventDefault();\r\n handleToolbarCommand(\"italic\");\r\n return;\r\n }\r\n // Underline: Ctrl/Cmd+U\r\n if (key === \"u\") {\r\n e.preventDefault();\r\n handleToolbarCommand(\"underline\");\r\n return;\r\n }\r\n // Undo: Ctrl/Cmd+Z\r\n if (key === \"z\") {\r\n e.preventDefault();\r\n // If Shift is pressed, treat as redo\r\n if (e.shiftKey) {\r\n handleRedo();\r\n } else {\r\n handleUndo();\r\n }\r\n return;\r\n }\r\n // Redo: Ctrl/Cmd+Y\r\n if (key === \"y\") {\r\n e.preventDefault();\r\n handleRedo();\r\n return;\r\n }\r\n },\r\n true\r\n );\r\n}\r\n","import {\r\n _setDoc,\r\n _getDoc,\r\n _setUndoStack,\r\n _getUndoStack,\r\n _setRedoStack,\r\n _getRedoStack,\r\n _setCurrentEditable,\r\n _getCurrentEditable,\r\n pushStandaloneSnapshot,\r\n} from \"./state\";\r\nimport { injectStyles } from \"../dom/styles\";\r\nimport { injectToolbar } from \"../toolbar/toolbar\";\r\nimport { attachStandaloneHandlers } from \"../dom/handlers\";\r\nimport { computeFormatState, getElementLabel } from \"../dom/format\";\r\nimport { handleUndo, handleRedo, handleToolbarCommand } from \"./commands\";\r\nimport type { EditorConfig } from \"./types\";\r\nimport { sanitizeHtml } from \"../utils/sanitize\";\r\nimport {\r\n TOOLBAR_ID,\r\n STYLE_ID,\r\n CLASS_EDITABLE,\r\n CLASS_ACTIVE,\r\n} from \"./constants\";\r\n\r\n/**\r\n * Initialize the rich HTML editor on an iframe element\r\n */\r\nexport function initRichEditor(\r\n iframe: HTMLIFrameElement,\r\n config?: EditorConfig\r\n) {\r\n try {\r\n if (!iframe || !(iframe instanceof HTMLIFrameElement)) {\r\n throw new Error(\"Invalid iframe element provided to initRichEditor\");\r\n }\r\n\r\n const doc = iframe.contentDocument;\r\n if (!doc) {\r\n throw new Error(\r\n \"Unable to access iframe contentDocument. Ensure iframe src is same-origin.\"\r\n );\r\n }\r\n\r\n _setDoc(doc);\r\n injectStyles(doc);\r\n _setUndoStack([]);\r\n _setRedoStack([]);\r\n _setCurrentEditable(null);\r\n if (config?.maxStackSize) {\r\n import(\"./state\")\r\n .then((m) => m.setMaxStackSize(config.maxStackSize!))\r\n .catch(() => {\r\n /* ignore */\r\n });\r\n }\r\n attachStandaloneHandlers(doc);\r\n pushStandaloneSnapshot();\r\n injectToolbar(doc, {\r\n onCommand: handleToolbarCommand,\r\n canUndo: () => _getUndoStack().length > 1,\r\n canRedo: () => _getRedoStack().length > 0,\r\n onUndo: handleUndo,\r\n onRedo: handleRedo,\r\n getFormatState: () => computeFormatState(doc),\r\n getSelectedElementInfo: () => getElementLabel(_getCurrentEditable()),\r\n });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Failed to initialize editor:\", message);\r\n throw error;\r\n }\r\n}\r\n\r\nexport function getCleanHTML(): string {\r\n try {\r\n const doc = _getDoc();\r\n if (!doc) {\r\n console.warn(\r\n \"[rich-html-editor] getCleanHTML called before editor initialization\"\r\n );\r\n return \"\";\r\n }\r\n if (!doc.documentElement) {\r\n throw new Error(\"Document is missing documentElement\");\r\n }\r\n\r\n const clone = doc.documentElement.cloneNode(true) as HTMLElement;\r\n\r\n // Remove injected toolbar and style elements if present\r\n const toolbarNode = clone.querySelector(`#${TOOLBAR_ID}`);\r\n if (toolbarNode && toolbarNode.parentNode)\r\n toolbarNode.parentNode.removeChild(toolbarNode);\r\n const styleNode = clone.querySelector(`#${STYLE_ID}`);\r\n if (styleNode && styleNode.parentNode)\r\n styleNode.parentNode.removeChild(styleNode);\r\n\r\n // Recursively clean root and descendants\r\n try {\r\n const cleanElement = (el: Element) => {\r\n try {\r\n // remove boolean/content attributes explicitly\r\n if (el.hasAttribute(\"contenteditable\"))\r\n el.removeAttribute(\"contenteditable\");\r\n if (el.hasAttribute(\"tabindex\")) el.removeAttribute(\"tabindex\");\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n\r\n try {\r\n const attrs = Array.from(el.attributes || []);\r\n attrs.forEach((a) => {\r\n const rawName = a.name;\r\n const name = rawName.toLowerCase();\r\n\r\n // remove inline event handlers\r\n if (name.startsWith(\"on\")) {\r\n try {\r\n el.removeAttribute(rawName);\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n return;\r\n }\r\n\r\n // remove any data-rhe-* attributes (including data-rhe-id)\r\n if (\r\n name === \"data-rhe-id\" ||\r\n name.startsWith(\"data-rhe-\") ||\r\n name === \"data-rhe\"\r\n ) {\r\n try {\r\n el.removeAttribute(rawName);\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n return;\r\n }\r\n });\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n\r\n try {\r\n if (el.id) {\r\n const id = el.id;\r\n if (\r\n id === TOOLBAR_ID ||\r\n id === STYLE_ID ||\r\n id.startsWith(\"editor-\") ||\r\n id.startsWith(\"rhe-\")\r\n ) {\r\n el.removeAttribute(\"id\");\r\n }\r\n }\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n\r\n try {\r\n const cls = Array.from(el.classList || []);\r\n cls.forEach((c) => {\r\n if (\r\n c === CLASS_EDITABLE ||\r\n c === CLASS_ACTIVE ||\r\n c.startsWith(\"editor-\") ||\r\n c.startsWith(\"rhe-\")\r\n ) {\r\n try {\r\n el.classList.remove(c);\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n }\r\n });\r\n\r\n // remove empty class attributes left behind\r\n if (\r\n el.hasAttribute(\"class\") &&\r\n (el.getAttribute(\"class\") || \"\").trim() === \"\"\r\n ) {\r\n try {\r\n el.removeAttribute(\"class\");\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n }\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n\r\n try {\r\n const children = Array.from(el.children || []);\r\n children.forEach((child) => cleanElement(child as Element));\r\n } catch (e) {\r\n /* ignore */\r\n }\r\n };\r\n\r\n // `instanceof Element` can fail across window/iframe boundaries\r\n // because each iframe has its own global `Element` constructor.\r\n // Use a cross-realm-safe check instead.\r\n if ((clone as Node).nodeType === Node.ELEMENT_NODE) {\r\n cleanElement(clone as Element);\r\n }\r\n } catch (e) {\r\n /* ignore traversal errors */\r\n }\r\n\r\n // Preserve original scripts intentionally.\r\n return \"<!doctype html>\\n\" + clone.outerHTML;\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Failed to get clean HTML:\", message);\r\n throw error;\r\n }\r\n}\r\n\r\nexport function getSanitizedHTML(): string {\r\n try {\r\n const doc = _getDoc();\r\n if (!doc) return \"\";\r\n if (!doc.documentElement)\r\n throw new Error(\"Document is missing documentElement\");\r\n const raw = \"<!doctype html>\\n\" + doc.documentElement.outerHTML;\r\n return sanitizeHtml(raw, doc);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.error(\"[rich-html-editor] Failed to get sanitized HTML:\", message);\r\n throw error;\r\n }\r\n}\r\n"],"mappings":"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","names":["input","newRange"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
_getCurrentEditable,
|
|
3
|
+
_getDoc,
|
|
4
|
+
_getRedoStack,
|
|
5
|
+
_getUndoStack,
|
|
6
|
+
_setCurrentEditable,
|
|
7
|
+
_setDoc,
|
|
8
|
+
_setRedoStack,
|
|
9
|
+
_setUndoStack,
|
|
10
|
+
pushStandaloneSnapshot,
|
|
11
|
+
setMaxStackSize
|
|
12
|
+
} from "./chunk-ZDGUOGND.mjs";
|
|
13
|
+
export {
|
|
14
|
+
_getCurrentEditable,
|
|
15
|
+
_getDoc,
|
|
16
|
+
_getRedoStack,
|
|
17
|
+
_getUndoStack,
|
|
18
|
+
_setCurrentEditable,
|
|
19
|
+
_setDoc,
|
|
20
|
+
_setRedoStack,
|
|
21
|
+
_setUndoStack,
|
|
22
|
+
pushStandaloneSnapshot,
|
|
23
|
+
setMaxStackSize
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=state-CZIMHTJ3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rich-html-editor",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Framework-agnostic rich HTML editor",
|
|
5
|
+
"author": "akshaypatil1",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/akshaypatil1/rich-html-editor.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/akshaypatil1/rich-html-editor/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/akshaypatil1/rich-html-editor#readme",
|
|
15
|
+
"main": "dist/index.cjs.js",
|
|
16
|
+
"module": "dist/index.mjs",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.mjs",
|
|
22
|
+
"require": "./dist/index.cjs.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"rich-editor",
|
|
32
|
+
"html-editor",
|
|
33
|
+
"rich-html-editor",
|
|
34
|
+
"wysiwyg",
|
|
35
|
+
"framework-agnostic",
|
|
36
|
+
"vanilla-js"
|
|
37
|
+
],
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"scripts": {
|
|
40
|
+
"clean": "rimraf dist",
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"prepare": "npm run build",
|
|
43
|
+
"prepublishOnly": "npm run build",
|
|
44
|
+
"test": "vitest",
|
|
45
|
+
"test:ui": "vitest --ui",
|
|
46
|
+
"test:coverage": "vitest --coverage"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@testing-library/dom": "^10.4.1",
|
|
50
|
+
"@testing-library/user-event": "^14.6.1",
|
|
51
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
52
|
+
"axe-core": "^4.10.0",
|
|
53
|
+
"jsdom": "^27.3.0",
|
|
54
|
+
"rimraf": "^5.0.0",
|
|
55
|
+
"tsup": "^8.0.0",
|
|
56
|
+
"typescript": "^5.3.0",
|
|
57
|
+
"vitest": "^4.0.15"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"dompurify": "^3.3.1"
|
|
61
|
+
}
|
|
62
|
+
}
|